Java教程

Java并发(十三):读写锁之间的锁降级和锁升级

本文主要是介绍Java并发(十三):读写锁之间的锁降级和锁升级,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

    • 回顾
    • 锁降级
    • 锁降级的必要性
    • 锁升级

回顾

之前已经分析了读写锁之间是如何进行加锁的,下面就看看,读写锁之间怎么进行锁降级与锁升级的

锁降级

读写锁的锁降级指的是写锁降级成为了读锁

当一个线程获取了写锁,并且又获取了读锁(获取写锁的线程可以获取读锁),那么当该线程释放了写锁时,该线程拥有的锁就会进行降级,变为了读锁,其实这个实现从之前看加锁源码就知道了,读锁和写锁的获取都是分开的,所以写锁的释放不会影响到读锁的持有

锁降级的必要性

锁降级的情景是,拿了写锁,然后再拿读锁,这有什么必要性吗?拿了写锁我就进行修改了,写锁已经限制了别人进行访问和修改了,我要读锁来干什么呢?

我觉得这个必要性是看场景的,只有当线程既需要写操作又需要读操作的时候,锁降级才有必要性

一般我们用锁进行操作数据时,都是下面三步

  • 获取锁
  • 操作数据
  • 释放锁

假如一个线程对某个数据进行先写后读操作,那么操作顺序一般变成下面所示

  • 获取写锁
  • 修改数据
  • 释放写锁
  • 获取读锁
  • 访问数据
  • 释放读锁

那么此时问题就出来了,在该线程释放写锁的一瞬间,就会有其他线程去获取写锁,那么该线程就会获取读锁失败,并且在线程在等待自旋获取读锁中,那么,当其他线程修改完数据并且释放了写锁,该线程再去获取读锁进行访问,就会出现无法感知其他线程对数据的修改状况出现

比如说,线程A获取写锁将变量修改成了5,然后释放了写锁,其他线程去获取写锁将变量修改成了6,线程A再获取了读锁进行访问变量,得到的结果为6,出现了幻觉一样,这就是没有感知到其他线程对数据修改,也就是幻读

所以,建议是获取了写锁之后,假如后续还要对数据进行访问,一定要获取读锁再释放写锁,拿到的读锁会限制写锁的获取

当然,可能会有人觉得,拿到了写锁之后,直接完成所有的读写操作再释放写锁不就好了吗?

这样做也是可以避免幻读产生的,但是逻辑不符合现实,并且效率会降低

  • 做完对应的操作就应该释放对应的锁,这是正确的逻辑,就好像上课去签到一样,只有一张签到表和一只笔,你签完名就应该放下笔让别人签,而不是为了看看班上有几个女生的名字而不放下笔,应该放下笔,在旁边看
  • 降低了效率,对于一些只读的线程,当前线程已经修改完了,就应该立刻释放写锁,让其他线程可以获取读锁来进行访问

锁升级

读写锁不支持锁升级。。。。。。

这篇关于Java并发(十三):读写锁之间的锁降级和锁升级的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!