APUE:如果线程试图对一个mutex加锁两次,那么它就会陷入死锁。
分析一下:
1. 第一次上锁成功后,获得锁
2. 第二次上锁时需要等待锁被本线程释放;而本线程目前已经在等待锁,无法释放第一次获得的锁;所以这个等待将是无限期的。
可重入锁(reentrant lock)就是用来避免这种情况发生的: 第二次上锁时不需要等待第一次上的锁被释放;java的ReentrantLock和synchronized关键字都使用了这种机制。
不过,Java里ReentractReadWriteLock在JDK 1.6 update 18 之前仍然可能造成单线程死锁:
- 拿到一个读锁,然后要求拿写锁。拿写锁时需要等待读锁被本线程释放(这里要拿的锁而已经锁上的锁是不同的,所以Reentrant不起作用),而本线程已经在等待写锁。无限循环的等待,造成死锁。这就是所谓的“读锁不可升级”