美文网首页Java 杂谈
Java使用读写锁替代同步锁

Java使用读写锁替代同步锁

作者: 野梦M | 来源:发表于2017-11-28 13:48 被阅读213次

应用情景

前一阵有个做反抄袭检测的小伙伴问了我一个问题。

---

在多线程里就是有个变量,我需要读取它来判断是否给它写入一些信息。

打算加锁,但是如果读取时候加入readlock,写入时候加入writelock,

这样做可能读写不同步。但是如果一起加lock效果就跟synchronized一样,效率变差

---

其实他的问题就是下面的场景:

高并发的读写请求

读取请求明显大于写入的请求

如果用synchronized同步锁会导致性能下降,本来读取是可以多线程同步进行的,同步锁就只能让他们一个一个排队读取。

如果读取时加readlock,写入时候加writelock,会提升效率,因为读可以多线程并发,但是在线程A读完上锁的毫秒级时间里,有可能线程B也读完了,而且抢在了线程A之前修改了变量,导致程序出错。

处理方案

我去研究了下读写锁,后来发现其实java官方已经给了答案。使用读写锁加标志位解决读写不同步的问题。Java ReentrantReadWriteLock

在这先普及下读写锁。

读锁:

读锁拒绝其他线程获得写锁,读锁不拒绝其他线程获得读锁,多个上了读锁的线程可以并发读不会阻塞。

多个读锁同时作用期间,其他想上写锁的线程都处在等待状态,当最后一个读锁释放后,才有可能上锁。

写锁:

写锁拒绝其他线程获取读锁和写锁。

当一个线程获取写锁后,其他想要获取读写锁的线程都处于等待状态,直到写锁释放才有可能上锁。

##代码实例

直接拿Java官方示例解读了。

classCachedData{Objectdata;  volatile boolean cacheValid;  final ReentrantReadWriteLock rwl =newReentrantReadWriteLock();voidprocessCachedData() {    rwl.readLock().lock();//1. 上读锁if(!cacheValid) {//2. 验证cacheValid// Must release read lock before acquiring write lockrwl.readLock().unlock();//3. 解除读锁rwl.writeLock().lock();//4. 上写锁try{// Recheck state because another thread might have// acquired write lock and changed state before we did.if(!cacheValid) {//5. 验证cacheValiddata = ...            cacheValid =true;          }// Downgrade by acquiring read lock before releasing write lockrwl.readLock().lock();//6. 上读锁}finally{          rwl.writeLock().unlock();// Unlock write, still hold read //7. 解除写锁}    }try{      use(data);    }finally{      rwl.readLock().unlock();//8. 解除读锁}  } }

比如现在有线程ABCDE五个线程,使用processCachedData()方法,接下来会发现如下步骤。

-> DE线程滞后,ABC同时进入到步骤1. 上读锁

-> ABC进入到步骤2. 验证cacheValid。(新实例中cacheValid初始为fasle,所以进入if条件句中)

-> ABC执行步骤3. 解除读锁。

-> 假设此时A率先完成步骤4. 上写锁。

-> BC无法获取写锁,处于等待状态,被阻塞在步骤4。 上写锁。此时D线程执行使用processCachedData()方法,被阻塞在步骤1. 上读锁。

-> A进入到步骤5. 验证cacheValid。

步骤五很关键,如果线程A写完后,解除了写锁,此时新的线程E获取到了写锁,就会写入新数据,此时就不是同步锁了,程序出错。

-> A修改数据,cacheValid置为true。步骤6和步骤7是写锁的降级操作,即写锁释放的时候,先降级为读锁,这样其他等待获取写锁的线程会继续等待,然后再释放写锁,保证同步性。

-> A执行完步骤8,BC阻塞结束,其中一位获取写锁。

如果你在学习Java的过程中或者在工作中遇到什么问题都可以来群里提问,阿里Java高级大牛直播讲解知识点,分享知识,多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!可以加群找我要课堂链接 注意:是免费的 没有开发经验误入哦! 非喜勿入! 学习交流QQ群:478052716

相关文章

  • Java使用读写锁替代同步锁

    应用情景 前一阵有个做反抄袭检测的小伙伴问了我一个问题。 --- 在多线程里就是有个变量,我需要读取它来判断是否给...

  • ReentrantReadWriteLock源码解析

    ReentrantReadWriteLock编码示例 上面的代码展示读写锁的使用,读写锁的介绍参考Java锁[ht...

  • 读写锁和互斥锁的区别

    同步 互斥锁 读写锁 区别

  • 读写锁的原理

    读写锁的使用 读写锁在 Java 中是 ReentrantReadWriteLock,使用方式是: Reentra...

  • Java并发编程-2

    Java中的显示Lock一 Lock接口二 队列同步器 AQS三 重入锁ReentrantLock四 读写锁 Re...

  • 十一 .Java并发工具

    Java中的锁 锁是一种线程同步机制,类似同步块,但是锁比Java的同步块更复杂。锁(以及其他更高级的同步机制)是...

  • java-summery

    1、对象锁和类锁 java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码...

  • Lock(锁)

    从JDK5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象...

  • Synchronized&Lock&AQS

    ?1.java锁 ?2.Synchronized锁的使用与原理 加锁方式:(1)、同步方法锁,进入方法前获取当前类...

  • 锁2

    5、读写锁 相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些。假设你的程序中涉及到...

网友评论

    本文标题:Java使用读写锁替代同步锁

    本文链接:https://www.haomeiwen.com/subject/jlhjbxtx.html