一、Lock接口
在Java SE 5之后,并发包新增了Lock接口用来实现锁功能。
相比于synchronize关键字:Lock虽然缺少了synchronize隐式获取释放锁的便捷性,但是多出了可操作性性。
例如:可中断获取锁,超时获取锁等功能。
二、重入锁
-
公平锁和非公平锁:重入锁支持获取锁时公平性的选择。
公平锁就是按照线程等待的时间来获取锁,保证绝对的公平性,减少“饥饿”的发生概率。
非公平锁就是不按照等待的时间顺序来获取锁。实际上非公平锁的效率远远高于公平锁,因为减少了线程间的切换,保证了更大的吞吐量。 -
实现重进入
重进入指任意进程获取锁之后能够再次获取该锁不会被锁所阻塞;
首先,锁需要去识别获取锁的线程是不是当前占据锁的线程,如果是则获取锁成功。
接着,锁每次获取进行自增计数,被释放则进行自减计数。直到计数为0时,锁被成功释放。
三、读写锁
- 读写状态的设计
如果是在一个整形变量上维护多种状态,就一定需要“按位切割使用”这个变量。读写锁将变量分为两个部分,高16位表示读,低16位表示写。无论是高位低位不为0时,则代表获取了锁。每次重进入则+1; - 写锁的获取与释放
写锁是支持重进入的排他锁。如果当前线程已经获取了锁,则增加写状态。
获取写锁时要判断是否存在读锁,若存在则要等待读锁释放后才能获取写锁。因为要保证写操作对所有读操作可见。 - 读锁的获取与释放
读锁是支持重进入的共享锁。如果在写状态为0时,读锁总是会被成功的获取。
读锁每次重进入增加读状态(1<<16),读锁每次进入都是线程安全的,依靠CAS保证。 - 锁降级
锁降级就是一个线程先获得了写锁,再获取读锁,最后成功的释放了写锁。那么写锁就成功降级为读锁了。