第十三章、显示锁
1.内部锁synchronized的缺点:不能中断那些正在等待获取锁的线程,并且在请求锁失败的情况下必须无限地等待。相比直线ReentrantLock为处理不可用锁,提供了更加灵活的操作。
2.ReentrantLock优点:可轮询,可定时,可中断。缺点:当锁忘记释放的时候,就很难排查到错误;写法不比synchronized简略。
3.在大多数情况下,非公平锁的优势超过了公平锁(联想:线程的抢占CPU的方式)synchronized是非公平锁。
4.ReentrantLock与synchronized选择:当你需要以下高级特性的时候才应该使用:可定时的,可轮询的,可中断的锁获取操作,公平队列或者非块结构的锁时使用ReentrantLock,否则使用synchronized。简而言之,如非项目确切需求,通常是使用synchronized。
5.JDK1.5到JDK1.6对锁的优化:
(1)自旋锁与自适应自旋:已经得到CPU时间,但是还在等待锁的线程,让它进入忙循环(自旋),这就是自旋锁。可以减少挂起与恢复的开销,但是如果自旋太久,又会浪费CPU资源。因此JDK1.6加入自适应锁,它自旋的时间不再固定,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。程序运行时间越久,自适应锁的自旋次数就越合理。
(2)锁消除:在写代码的时候,有时候会不自觉地加入锁(例如在非多线程的环境下调用线程安全的方法,像StringBuffer那种),此时如果可以,JVM会消除锁。
(3)锁粗化:比如在一个循环中反复地对一个对象进行加锁和解锁,那么JVM会将此锁进行粗化到循环到外部
(4)轻量级锁:在没有多线程竞争的前提下,使用CAS操作去消除同步使用的互斥量。
(5)偏向锁:在没有多线程竞争的前提下,把整个同步都消除掉,连CAS都不做。这个锁会偏向于第一个获得它的线程,如果在接下来的执行过程中,该锁没有被其他的线程获取,则持有偏向锁的线程将永远不需要再进行同步。
6.读写锁:在可以消除读/读这种情况的锁的竞争。