(JAVA)(ReadWriteLock)读写锁

首先自定义一个缓存来实现程序的读(get)和写(put)操作。在自定义缓存(这里使用HashMap定义缓存)的时候会使用volatile关键字,volatile关键字的特点可以保证操作的可见性,但不一定保证操作的原子性。为什么要保证操作的可见性,这里简略说一下,因为在多线程情况下如果线程A对缓存进行操作,线程B也对缓存进行操作,在A写入缓存的时候B也写入缓存,会出现B的写入对A的写入覆盖的情况,程序会抛出异常,还有其他的数据异常的情况会出现,详情可以了解java中多线程。

class MyCache1{
    private volatile Map<String,Object> map = new HashMap<>();
    // 写 ,存
    public void put(String key,Object value){
        System.out.println(Thread.currentThread().getName()+"写入start");
        map.put(key,value);
        System.out.println(Thread.currentThread().getName()+"写入ok");
    }
    // 读 ,取
    public void get(String key){
        System.out.println(Thread.currentThread().getName()+"读取start");
        Object o = map.get(key);
        System.out.println(Thread.currentThread().getName()+"读取ok");
    }
}

通过普通的多线程执行:

// 读写锁
public class test_04 {
    public static void main(String[] args) {
        MyCache1 cache = new MyCache1(); // 自定义缓存,普通执行
        // 写
        for (int i = 0; i < 5; i++) {
            final int t = i;
            new Thread(()->{
                cache.put("t = "+ t,t);
            },String.valueOf(i)).start();
        }
        // 读
        for (int i = 0; i < 5; i++) {
            final int t = i;
            new Thread(()->{
                cache.get(t+"");
            },String.valueOf(i)).start();
        }
    }
}

执行结果:
在这里插入图片描述

我们发现这个写入的读取顺序已经变成了乱序,在线程1写入还没有完成的时候,线程2就已经写入完成,那么线程2的写入已经覆盖了线程1之前的写入,这种多线程操作是不可取的,因此在这个时候我们就要用到读写锁(ReadWriteLock)。

加上读写锁(ReadWriteLock)的多线程程序:

// 加锁的缓存
class MyCache2{
    private volatile Map<String,Object> map = new HashMap<>();
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    // 写 ,存 只有一个人可以写
    public void put(String key,Object value){
        lock.writeLock().lock(); // 写锁加锁
        System.out.println(Thread.currentThread().getName()+"写入start");
        map.put(key,value);
        System.out.println(Thread.currentThread().getName()+"写入ok");
        lock.writeLock().unlock();
    }
    // 读 ,取 所有人都可以读
    public void get(String key){
        lock.readLock().lock();
        System.out.println(Thread.currentThread().getName()+"读取写入start");
        Object o = map.get(key);
        System.out.println(Thread.currentThread().getName()+"读取ok");
        lock.readLock().unlock();
    }
}

执行结果:在这里插入图片描述

这里注意一下写锁和读锁的区别:
读锁是一种共享锁,所有线程都可以读。
写锁是一种排他锁,即在线程写入的时候,只能有一个线程获得缓存的写入权限,避免多个线程写入对缓存内容进行覆盖。
所以每个线程在写入缓存的时候都独占该缓存,等写入完成释放资源后,其他线程才可以对缓存进行写入,在读的时候所有线程都可以同时读。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值