JAVA 并发编程-读写锁之模拟缓存系统(十一)

   

    在多线程中,为了提高效率有些共享资源允许同时进行多个读的操作,但只允许一个写的操作,比如一个文件,只要其内容不变可以让多个线程同时读,不必做排他的锁定,排他的锁定只有在写的时候需要,以保证别的线程不会看到数据不完整的文件。这时候就需要使用读写锁。


/**
 * 简单读写锁demo
 * @author hejingyuan
 *
 */
public class ReadWriteLockTest {
	public static void main(String[] args) {
		final Queue3 q3 = new Queue3();
		//创建几个线程
		for(int i=0;i<3;i++)
		{
			new Thread(){
				public void run(){
					while(true){
						q3.get();						
					}
				}
				
			}.start();
			
			new Thread(){
				public void run(){
					while(true){
						q3.put(new Random().nextInt(10000));
					}
				}			
				
			}.start();
			
		}
		
	}
}

class Queue3{
	private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据
	//读写锁
	ReadWriteLock rwl = new ReentrantReadWriteLock();
	//读数据
	public void get(){
		rwl.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " be ready to read data!");
			Thread.sleep((long)(Math.random()*1000));
			System.out.println(Thread.currentThread().getName() + "have read data :" + data);			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.readLock().unlock();
		}
	}
	//写数据
	public void put(Object data){

		rwl.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " be ready to write data!");					
			Thread.sleep((long)(Math.random()*1000));
			this.data = data;		
			System.out.println(Thread.currentThread().getName() + " have write data: " + data);					
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.writeLock().unlock();
		}
		
	
	}
}

运行结果:

 

Thread-0 be ready to readdata!

Thread-2 be ready to readdata!

Thread-2have read data:null

Thread-0have read data:null

Thread-1 be ready towrite data!

Thread-1 have write data:1021

Thread-1 be ready towrite data!

Thread-1 have write data:2887

 

看到这里不免有人会问,既然读的时候可以多人访问,那么为什么还要加读锁呢?

答:当然要加锁了,否则在写时去读,可能不正确(写的时候不能去读)

 

读写锁模拟缓存系统实现:


public class CacheDemo {

	private Map<String, Object> cache = new HashMap<String, Object>();
	public static void main(String[] args) {
		

	}

	//定义读写锁
	private ReadWriteLock rwl = new ReentrantReadWriteLock();
	//读数据,使用读锁
	public  Object getData(String key){
		//添加读锁
		rwl.readLock().lock();
		Object value = null;
		try{
			value = cache.get(key);
			if(value == null){
				//释放读锁
				rwl.readLock().unlock();
				//加上写锁
				rwl.writeLock().lock();
				try{
					//假设三个线程同时去获取写锁,我们知道只有第一个线程能够获取
                    //那么其他两个线程只有等了,如果第一个线程按流程执行完后,刚才的两个线程可以得到写锁了,
                    //然后接着就可以修改数据了(赋值).所以加上判断!
					if(value==null){//为什么还要判断?
						value = "aaaa";//实际是去queryDB();
					}
				}finally{
					//释放写锁
					rwl.writeLock().unlock();
				}
				rwl.readLock().lock();
			}
		}finally{
			rwl.readLock().unlock();
		}
		return value;
	}
}

总结:

 

    读写锁的作用为,当我们加上写锁时,其他线程被阻塞,只有一个写操作在执行,当我们加上读锁后,它是不会限制多个读线程去访问的。也就是getput之间是互斥的,put与任何线程均为互斥,但是getget线程间并不是互斥的。其实加读写锁的目的是同一把锁的读锁既可以与写锁互斥,读锁之间还可以共享。

    原文作者:java锁
    原文地址: https://blog.csdn.net/hejingyuan6/article/details/47070373
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞