10. JUC读写锁ReentrantReadWriteLock

简介

为了满足并发的要求,多个线程同时读取一个资源类应该可以同时进行,但是如果有一个线程想去写共享资源,此时就不应该再有其它线程可以对该资源进行读或写。

*独占锁(写)/共享锁(读)/互斥锁

  1. 独占锁

    指该锁一次只能被一个线程所持有,ReentrantLock和synchronized都是独占锁

  2. 共享锁

    指该锁可被多个线程所持有

*不加锁

会导致顺序混乱,数据不一致,如果使用lock的话,会导致读写都加锁,但是我们只需要给写加锁,不需要给读加锁

public class ReadWriteLockDemo{
	public static void main(String[] args){
		MyCache m = new MyCache();
		for(int i = 1; i <= 5; i++){
			final int tempNum = i;
			new Thread(() -> {
				m.put(tempNum + "" , tempNum + "");
			},String.valueOf(i)).start();
		}
		
		for(int i = 1; i <= 5; i++){
			final int tempNum = i;
			new Thread(() -> {
				m.get(tempNum + "");
			},String.valueOf(i)).start();
		}
	}
}

class MyCache{
	private volatile Map<String, Object> map = new HashMap<>();
	
	/**
	 * 写操作的特征:原子+独占
	 * 整个过程必须是一个完整的统一体,中间不许被分割,被打断
	 */ 
	public void put(String k, Object v){
		try{
			System.out.println(Thread.currentThread().getName() + "\t开始写入" + k);
			TimeUnit.MILLISECONDS.sleep(300);
			map.put(k , v);
			System.out.println(Thread.currentThread().getName() + "\t写入完成");
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
	/**
	 * 读的特征:可与其他线程共享资源,且时间不一样
	 */
	public void get(String k){
		try{
			System.out.println(Thread.currentThread().getName() + "\t开始读取");
			TimeUnit.MILLISECONDS.sleep(300);
			Object o = map.get(k);
			System.out.println(Thread.currentThread().getName() + "\t读取完成" + o);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
}

读写锁

class MyCache{
	private volatile Map<String, Object> map = new HashMap<>();
	private ReadWriteLock r = new ReentrantReadWriteLock();
	
	public void put(String k, Object v){
		r.writeLock().lock();
		try{
			System.out.println(Thread.currentThread().getName() + "\t开始写入" + k);
			TimeUnit.MILLISECONDS.sleep(300);
			map.put(k , v);
			System.out.println(Thread.currentThread().getName() + "\t写入完成");
		}catch(InterruptedException e){
			e.printStackTrace();
		}finally{
			r.writeLock().unlock();
		}
	}
	
	public void get(String k){
		r.readLock().lock();
		try{
			System.out.println(Thread.currentThread().getName() + "\t开始读取");
			TimeUnit.MILLISECONDS.sleep(300);
			Object o = map.get(k);
			System.out.println(Thread.currentThread().getName() + "\t读取完成" + o);
		}catch(InterruptedException e){
			e.printStackTrace();
		}finally{
			r.readLock().unlock();	
		}
	}
}

*总结

读的线程执行时,可以同时执行其它读的线程,但是不能执行写的线程

写的线程执行时,最好一个一个写入,不能执行读的线程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值