【锁】1 Lock的优势与特性
Lock和synchronized是最常见的锁,用于控制对共享资源的访问。Lock不是用来代替synchronized的,而是synchronized不满足要求时,提供更高级的功能。Lock接口常见实现类是ReentrantLock和ReadWriteLock。
synchronized的缺点,参见之前的小节。
- 锁效率低
-
锁的释放情况少。synchronized监视器锁在方法或代码块正常退出和异常时释放锁。 试图获得锁时不能设置超时、不能中断一个正在试图获得锁的线程。
- 不够灵活 相对于读写锁,加锁和释放的时机单一,每个锁只有单一条件(锁定某个对象),可能不够。
- 无法知道是否成功获取到锁。 例如Lock的tryLock方法
1 Lock接口分析
public interface Lock { // 获取锁 void lock(); // 获取锁时可以被中断 void lockInterruptibly() throws InterruptedException; boolean tryLock(); // 超时就放弃 boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 解锁 void unlock(); Condition newCondition(); }
-
Lock不会像synchronized在异常时释放锁,因此需要在finally调用unlock,确保锁被释放。 lock()方法不能被中断,一旦死锁,会陷入永久等待。 tryLock()用来尝试获取锁,如果当前锁未被其他线程占用,则获取锁,并返回true;否则返回false。方法立即返回,即使拿不到锁也会等待。
tryLock代码规范,参考注释
Lock lock = new ReentrantLock(); if(lock.tryLock()) { try { } finally { lock.unlock(); } }
线程等待Lock锁时是WAITING状态,不可能是BLOCKED.
2 Lock的可见性保证
Lock的可见性与synchronized相同,可以参考happens-before原则。解锁操作对之后的加锁操作可见。
lock和unlock对齐内存交互操作中的lock和unlock操作。
3 演示示例
本文案例代码位置: