首页 > 代码库 > JAVA多线程(八)模式-Read Write Lock

JAVA多线程(八)模式-Read Write Lock

Read Write Lock

写入是互斥的,读取是共享的,写入与读取不能同时发生。

适用环境

类似缓存更新的场景。

样例

缓存,多读多写,LRU淘汰。

读写锁

读读共享,读写、写写互斥。

package ReadWriteLock;

public class ReadWriteLock {
	private int waitWriters=0;
	private int writingWriters=0;
	private int readers=0;
	//读写都在等待时,写优先,读线程多,写线程少,防止写线程被饿死
	private boolean writeFirst=true;
	
	public synchronized void readLock() throws InterruptedException{		
		while(writingWriters>0||(writeFirst&&waitWriters>0)){
			wait();
		}
		readers++;
		showDetail(Thread.currentThread().getName()+"--"+"readLock");
	}
	public synchronized void readUnlock(){
		readers--;
		writeFirst=true;
		showDetail(Thread.currentThread().getName()+"--"+"readUnlock");
		notifyAll();
	}
	
	public synchronized void writeLock() throws InterruptedException{
		waitWriters++;
		try{
			//读、写过程中不能再写,等待
			while(readers>0||writingWriters>0){
				wait();
			}
		}finally{
			waitWriters--;
		}
		writingWriters++;
		showDetail(Thread.currentThread().getName()+"--"+"writeLock");
	}
	public synchronized void writeUnlock(){
		//释放写锁
		writingWriters--;
		//写过,同时等待中的读、写中,读优先。避免连续写,读线程饥饿
		writeFirst=false;
		showDetail(Thread.currentThread().getName()+"--"+"writeUnlock");
		notifyAll();
	}
	
	private void showDetail(String msg){
		System.out.println(Thread.currentThread().getName()+"--"+"--------------------------");
		System.out.println(Thread.currentThread().getName()+"--"+msg);
		System.out.println(Thread.currentThread().getName()+"--"+"wait:"+waitWriters);
		System.out.println(Thread.currentThread().getName()+"--"+"writing:"+writingWriters);
		System.out.println(Thread.currentThread().getName()+"--"+"read:"+readers);
		
		System.out.println(Thread.currentThread().getName()+"--"+"--------------------------");
	}
	
}

缓存

基于LinkedHashMap实现

package ReadWriteLock;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

public class SharedBuffer<K,V> {
	private ReadWriteLock lock=new ReadWriteLock();
	private LinkedHashMap<K,V> buf=null;
	private final int size;
	public SharedBuffer(final int initsize){
		this.size=(int) Math.ceil(initsize / 0.75f) + 1;
		this.buf=new LinkedHashMap<K,V>(size, 0.75f, true) {
			private static final long serialVersionUID = -2347727619006196448L;
			@Override
			protected boolean removeEldestEntry(Entry<K,V> eldest) {
				boolean isRemove=size() > initsize;
				if(isRemove){
					System.out.println(Thread.currentThread().getName()+"--"+eldest.getKey()+":"+eldest.getValue()+" 被丢弃!");
				}
                return isRemove;
            }
        };
	}
	
	public void put(K k,V v){
		try {
			lock.writeLock();
			System.out.println(Thread.currentThread().getName()+"--"+"buffer after write lock");
			System.out.println(Thread.currentThread().getName()+"--"+this.showSnapHost());
		} catch (InterruptedException e) {
			
		}
		try{
			this.buf.put(k, v);
			System.out.println(Thread.currentThread().getName()+"--"+"buffer "+k+"->"+v);
		}finally{
			System.out.println(Thread.currentThread().getName()+"--"+this.showSnapHost());
			lock.writeUnlock();
			System.out.println(Thread.currentThread().getName()+"--"+"buffer after write unlock");
		}
	}
	public V get(K k){
		try {
			System.out.println(Thread.currentThread().getName()+"--"+"buffer before read lock");
			lock.readLock();
			System.out.println(Thread.currentThread().getName()+"--"+"buffer after read lock");			
		} catch (InterruptedException e) {
			
		}
		try {
			return this.buf.get(k);
		}finally{
			System.out.println(Thread.currentThread().getName()+"--"+this.showSnapHost());
			lock.readUnlock();
			System.out.println(Thread.currentThread().getName()+"--"+"buffer read unlock");
		}
	}

	private String showSnapHost() {
		Map<K,V> copy = new LinkedHashMap<K,V>(this.buf);
		StringBuilder sb = new StringBuilder();
		for (Map.Entry<K,V> entry : copy.entrySet()) {
			sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue()));
		}
		return sb.toString();
    }
}

读者

package ReadWriteLock;

import java.util.Random;

public class Reader implements Runnable{

	private final SharedBuffer<String,String> buf;
	private final String myName;
	public Reader(String myName,SharedBuffer<String,String> buf){
		this.myName=myName;
		this.buf=buf;
	}
	@Override
	public void run() {
		Random r=new Random();
		while(true){
			String k=Integer.toString(r.nextInt(10));
			System.out.println(Thread.currentThread().getName()+"--"+k+" Readed!!! "+this.myName+":"+buf.get(k));
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}

}

写者

package ReadWriteLock;

import java.util.Random;

public class Writer implements Runnable{

	private final SharedBuffer<String,String> buf;
	private final String myName;
	public Writer(String myName,SharedBuffer<String,String> buf){
		this.myName=myName;
		this.buf=buf;
	}
	@Override
	public void run() {
		Random r=new Random();
		int cnt=0;
		while(true){
			cnt++;
			String k=null;
			if(cnt<=10){
				k=Integer.toString(r.nextInt(10));
			}else{
				k=Integer.toString(r.nextInt(100));
			}
			
			buf.put(k, ""+cnt);
			System.out.println(Thread.currentThread().getName()+"--"+k+" writed!! "+this.myName+":"+cnt);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

测试类

package ReadWriteLock;

public class Test {

	public static void main(String[] args) {
		System.out.println("++++++++++++++++++++++++++++++++++++");
		SharedBuffer<String,String> buf=new SharedBuffer<String,String>(10);
		Reader r1=new Reader("r1",buf);
		Reader r2=new Reader("r2",buf);
		
		Writer w1=new Writer("w1",buf);
		Writer w2=new Writer("w2",buf);
		
		Thread rtd1=new Thread(r1);
		Thread rtd2=new Thread(r2);
		
		Thread wtd1=new Thread(w1);
		Thread wtd2=new Thread(w2);
		
		wtd1.start();
		wtd2.start();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		rtd1.start();
		rtd2.start();
		
		
		try {
			rtd1.join();
			rtd2.join();
			wtd1.join();
			wtd2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

本文出自 “JAVA技术栈笔记” 博客,请务必保留此出处http://stroll.blog.51cto.com/11038467/1857276

JAVA多线程(八)模式-Read Write Lock