ReenTrantLock可重入锁(和synchronized的区别)总结
重入性: ReenTrantLock和synchronized都是可重入锁。 同一个线程每进入一次,锁的计数器+1,等到锁的计数器降为0时才释放锁。
实现: Synchronized是依赖于JVM实现的,而ReenTrantLock是JDK实现的。
写法: Synchronized由编译器去保证锁的加锁和释放,而ReenTrantLock需要手工声明来加锁和释放锁,为了避免忘记手工释放锁造成死锁,所以最好在finally中声明释放锁。
锁类型: ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。
ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。
final Lock lock = new ReentrantLock();//锁对象final Condition notFull = lock.newCondition();//写线程条件 final Condition notEmpty = lock.newCondition();//读线程条件 lock.lock(); try { notFull.await();//阻塞写线程 //....... notEmpty.signal();//唤醒读线程 } finally { lock.unlock(); }
Object的 wait notify notifyAll FIFO
ReentrantLock 的condition的 await signal signalAll
ReentrantLock主要利用CAS+CLH队列来实现。
CAS: Compare and Swap,比较并交换。CAS有3个操作数:内存值V、预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。该操作是一个原子操作,被广泛的应用在Java的底层实现中。在Java中,CAS主要是由sun.misc.Unsafe这个类通过JNI调用CPU底层指令实现。
CLH队列:带头结点的双向非循环链表/** * 该锁同步控制的一个基类.下边有两个子类:非公平机制和公平机制.使用了AbstractQueuedSynchronizer类的 */static abstract class Sync extends AbstractQueuedSynchronizer (AQS)/** * 非公平锁同步器 */final static class NonfairSync extends Sync/** * 公平锁同步器 */final static class FairSync extends Sync /** 同步器:内部类Sync的一个引用 */private final Sync sync;/** * 创建一个锁 * @param fair true-->公平锁 false-->非公平锁 */public ReentrantLock(boolean fair) { sync = (fair)? new FairSync() : new NonfairSync();}
参考 https://blog.csdn.net/qq838642798/article/details/65441415