当线程尝试获取锁时 , 可重入锁先尝试获取并更新status值 , 如果status == 0表示没有其他线程在执行同步代码 , 则把status置为1 , 当前线程开始执行 。如果status != 0 , 则判断当前线程是否是获取到这个锁的线程 , 如果是的话执行status+1 , 且当前线程可以再次获取锁 。而非可重入锁是直接去获取并尝试更新当前status的值 , 如果status != 0的话会导致其获取锁失败 , 当前线程阻塞 。
释放锁时 , 可重入锁同样先获取当前status的值 , 在当前线程是持有锁的线程的前提下 。如果status-1 == 0 , 则表示当前线程所有重复获取锁的操作都已经执行完毕 , 然后该线程才会真正释放锁 。而非可重入锁则是在确定当前线程是持有锁的线程之后 , 直接将status置为0 , 将锁释放 。
文章插图
6. 独享锁 VS 共享锁独享锁和共享锁同样是一种概念 。我们先介绍一下具体的概念 , 然后通过ReentrantLock和ReentrantReadWriteLock的源码来介绍独享锁和共享锁 。
独享锁也叫排他锁 , 是指该锁一次只能被一个线程所持有 。如果线程T对数据A加上排它锁后 , 则其他线程不能再对A加任何类型的锁 。获得排它锁的线程即能读数据又能修改数据 。JDK中的synchronized和JUC中Lock的实现类就是互斥锁 。
共享锁是指该锁可被多个线程所持有 。如果线程T对数据A加上共享锁后 , 则其他线程只能对A再加共享锁 , 不能加排它锁 。获得共享锁的线程只能读数据 , 不能修改数据 。
独享锁与共享锁也是通过AQS来实现的 , 通过实现不同的方法 , 来实现独享或者共享 。
下图为ReentrantReadWriteLock的部分源码:
文章插图
我们看到ReentrantReadWriteLock有两把锁:ReadLock和WriteLock , 由词知意 , 一个读锁一个写锁 , 合称“读写锁” 。再进一步观察可以发现ReadLock和WriteLock是靠内部类Sync实现的锁 。Sync是AQS的一个子类 , 这种结构在CountDownLatch、ReentrantLock、Semaphore里面也都存在 。
在ReentrantReadWriteLock里面 , 读锁和写锁的锁主体都是Sync , 但读锁和写锁的加锁方式不一样 。读锁是共享锁 , 写锁是独享锁 。读锁的共享锁可保证并发读非常高效 , 而读写、写读、写写的过程互斥 , 因为读锁和写锁是分离的 。所以ReentrantReadWriteLock的并发性相比一般的互斥锁有了很大提升 。
那读锁和写锁的具体加锁方式有什么区别呢?在了解源码之前我们需要回顾一下其他知识 。
在最开始提及AQS的时候我们也提到了state字段(int类型 , 32位) , 该字段用来描述有多少线程获持有锁 。
在独享锁中这个值通常是0或者1(如果是重入锁的话state值就是重入的次数) , 在共享锁中state就是持有锁的数量 。但是在ReentrantReadWriteLock中有读、写两把锁 , 所以需要在一个整型变量state上分别描述读锁和写锁的数量(或者也可以叫状态) 。于是将state变量“按位切割”切分成了两个部分 , 高16位表示读锁状态(读锁个数) , 低16位表示写锁状态(写锁个数) 。如下图所示:
文章插图
了解了概念之后我们再来看代码 , 先看写锁的加锁源码:
文章插图
- 这段代码首先取到当前锁的个数c , 然后再通过c来获取写锁的个数w 。因为写锁是低16位 , 所以取低16位的最大值与当前的c做与运算( int w = exclusiveCount(c); ) , 高16位和0与运算后是0 , 剩下的就是低位运算的值 , 同时也是持有写锁的线程数目 。
- 在取到写锁线程的数目后 , 首先判断是否已经有线程持有了锁 。如果已经有线程持有了锁(c!=0) , 则查看当前写锁线程的数目 , 如果写线程数为0(即此时存在读锁)或者持有锁的线程不是当前线程就返回失败(涉及到公平锁和非公平锁的实现) 。
- 如果写入锁的数量大于最大数(65535 , 2的16次方-1)就抛出一个Error 。
推荐阅读
- Java虚拟机:Jvm概念和原理详解以及GC机制的分析
- Java|聊聊写简历的那些坑,为什么你投出去的简历总是石沉大海!
- 换一个卧室门锁大概多少钱,卧室门锁芯怎么换
- java 泛型详解
- WiFi系统的无线AP与AC之间的各种问题解析
- 吴裕泰连锁茶餐厅,品味精致茶文化菜肴
- 春吃芽,各种芽的功效大不同,你知道这其中的奥秘吗?
- 茶是毒素解药 不同人群喝不同的茶
- 电子驻车很多车上都有,带你解锁它的隐藏功能,别到卖车还不知道
- 肉苁蓉锁阳泡茶的方法是什么