java.util.concurrent.locks包提供了鎖和等待條件的接口和類, 可用於替代JDK1.5以前的同步(synchronized)和監視器機制(主要是Object類的wait(), notify(), notifyAll()方法).java
互斥鎖--Lock接口及其實現類ReentrantLock併發
所謂互斥鎖, 指的是一次最多隻能有一個線程持有的鎖. 在jdk1.5以前, 咱們一般使用synchronized機制控制多個線程對共享資源的訪問. 而如今, Lock提供了比synchronized機制更普遍的鎖定操做, Lock和synchronized機制的主要區別:高併發
Java代碼 性能
public class LockTest { private static Lock lock = new ReentrantLock(); public static void main(String[] args) { lock.lock(); invokeMethod(); } private static void invokeMethod() { lock.unlock(); } }
爲了確保鎖被釋放, 一般會採用以下的代碼形式:this
Java代碼 線程
Lock lock = new ReentrantLock(); // 獲取鎖 lock.lock(); try { // access the resource protected by this lock } finally { // 釋放鎖 lock.unlock(); }
|--void lock(): 執行此方法時, 若是鎖處於空閒狀態, 當前線程將獲取到鎖. 相反, 若是鎖已經被其餘線程持有, 將禁用當前線程, 直到當前線程獲取到鎖.code
|--void unlock(): 執行此方法時, 當前線程將釋放持有的鎖. 鎖只能由持有者釋放, 若是線程並不持有鎖, 卻執行該方法, 可能致使異常的發生.orm
|--boolean tryLock(): 若是鎖可用, 則獲取鎖, 並當即返回true, 不然返回false. 該方法和lock()的區別在於, tryLock()只是"試圖"獲取鎖, 若是鎖不可用, 不會致使當前線程被禁用, 當前線程仍然繼續往下執行代碼. 而lock()方法則是必定要獲取到鎖, 若是鎖不可用, 就一直等待, 在未得到鎖以前,當前線程並不繼續向下執行. 一般採用以下的代碼形式調用tryLock()方法:對象
Java代碼 blog
Lock lock = new ReentrantLock(); if (lock.tryLock()) { try { // manipulate protected state } finally { lock.unlock(); } } else { // perform alternative actions }
此用法可確保若是獲取了鎖, 則會釋放鎖; 若是未獲取鎖, 則不會試圖將其釋放.
條件--Condition
調用Condition對象的相關方法, 能夠方便的掛起和喚醒線程. Object對象的wait(), notify(), notifyAll()方法固然也能夠作到這一點, 可是Object對象的這些方法存在很不方便的地方--若是多個線程調用了obj的wait()方法而掛起, 那麼咱們沒法作到調用obj的notify()和notifyAll()方法喚醒其中特定的一個線程. 而Condition對象就能夠作到這一點. 具體的代碼請參見個人上一篇博客http://coolxing.iteye.com/blog/1236696中的解法二部分.
讀寫鎖--ReadWriteLock接口及其實現類ReentrantReadWriteLock
ReentrantReadWriteLock中定義了2個內部類, ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock, 分別用來表明讀取鎖和寫入鎖. ReentrantReadWriteLock對象提供了readLock()和writeLock()方法, 用於獲取讀取鎖和寫入鎖.
使用讀寫鎖的一個例子:
Java代碼
public class ReadWriteLockTest { private static ReadWriteLock lock = new ReentrantReadWriteLock(); private static Person person = new Person("David Beckham", true); public static void main(String[] args) { new Thread() { public void run() { while(true) { try { lock.readLock().lock(); System.out.print("name = " + person.getName()); System.out.println(", isMan = " + person.isMan()); } finally { lock.readLock().unlock(); } } }; }.start(); new Thread() { public void run() { boolean state = true; while(true) { try { lock.writeLock().lock(); if (state) { person.setName("Lady GaGa"); person.setMan(false); state = false; } else { person.setName("David Beckham"); person.setMan(true); state = true; } } finally { lock.writeLock().unlock(); } } }; }.start(); } } class Person { private String name; private boolean isMan; public Person(String name, boolean isMan) { this.name = name; this.isMan = isMan; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isMan() { return isMan; } public void setMan(boolean isMan) { this.isMan = isMan; } }
無論程序運行多久, 也不會有人妖的出現.