一、Lock与ReentrantLock
Lock接口中定义了一种无条件、可轮询的、定时的以及可中断的锁获取操作,所有加锁和解锁的方法都是显式的。
1 public interfece Lock 2 { 3 void lock(); 4 void lockInterruptibly() throws InterruptedException; 5 boolean tryLock(); 6 boolean tryLock(long timeout, TimeUnit unit 7 throw InterruptedException; 8 void unlock(); 9 Condition newCondition(); 10 }
ReentrantLock实现了Lock接口,并提供了与synchronized相同的互斥性和内存可见性。ReentrantLock同样提供了可重入的加锁语义
1 Lock lock = new ReentrantLock(); 2 ... 3 lock.lock(); 4 try { 5 // 更新对象状态 6 // 捕获异常,并在必要时恢复不变性条件 7 } finally { 8 lock.unlock();//一定要记得在finally块里释放 9 }
1、轮询锁与定时锁
- 轮询锁和定时锁可由tryLock来实现
- 轮询锁,定时锁可以避免死锁的发生
- 轮询锁通过释放已获得的锁,并退回重新尝试获取所有锁(lock.tryLock()),定时锁通过释放已获得的锁,放弃本次操作(lock.tryLock(timeout, unit))来避免死锁
1 while (true) { 2 if (fromAcct.lock.tryLock()) { 3 try { 4 if (toAcct.lock.tryLock()) { 5 try { 6 if (fromAcct.getBalance().compareTo(amount) < 0) 7 throw new InsufficientFundsException(); 8 else { 9 fromAcct.debit(amount); 10 toAcct.credit(amount); 11 return true; 12 } 13 } finally { 14 toAcct.lock.unlock(); 15 } 16 } 17 } finally { 18 fromAcct.lock.unlock(); 19 } 20 } 21 if (System.nanoTime() < stopTime) 22 return false; 23 NANOSECONDS.sleep(fixedDelay + rnd.nextLong() % randMod); 24 } 25 }