在JDK1.5中新增長了ReentrantLock類頁可以實現同步的效果,並且在擴張功能上也更增強大,使用上也更加方便。java
ReentrantLock線程
首先先看一下ReentrantLock的方法:code
而後來看一個ReentrantLock的使用實例。對象
public class Service extends Thread { private Lock lock = new ReentrantLock(); public void run(){ lock.lock(); for(int i = 0; i < 5; i++){ System.out.println(Thread,currentThread().getName()); } lock.unLock(); } public static void main(String [] args){ Service s1 = new Service(); Service s2 = new Service(); Service s3 = new Service(); s1.start(); s2.start(); s3.start(); } 運行結果:每一個線程是同步的,但哪一個線程先執行是不必定的。
調用ReentrantLock對象的lock()方法獲取鎖,調用unlock()方法釋放鎖。unLock()方法也可放到finally代碼塊中。get
Condition同步
首先先看一下Condition類的方法:it
Condition對象至關於「對象監視器」實例,線程對象能夠註冊在指定的Condition中,從而能夠有選擇性的進行線程通知,在調度線程上更加靈活。而synchronized就至關於整個Lock對象中就只有一個單一的Condition,全部線程都註冊到一個Condition中,線程開始notifyAll時,須要通知全部的WAITING線程。io
public class MyThread extends Thread { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void run(){ lock.lock(); condition.await(); lock.unLock(); } public static void main(String [] args){ MyThread t = new MyThread(); t.start(); } }
在調用Condition的await方法以前,必需要先得到鎖,即必須先調用Lock的lock方法,不然會拋出異常。class
用Condition實現等待/通知模式效率
Condition中的await()方法至關於wait()方法,signal()/signalAll()方法至關於notify()/notifyAll()方法。
使用多個Condition實現通知部分線程
既要先對線程組進行分類,而後在喚醒指定組中的線程
public class MyService { private Lock lock = new ReentrantLock(); private Condition conditionA = lock.newCondition(); private Condition conditionB = lock.newCondition(); public void awaitA(){ lock.lock(); conditionA.await(); lock.unLock(); } public void awaitB(){ lock.lock(); conditionB.await(); lock.unLock(); } public void signalA(){ lock.lock(); conditionA.signalAll(); lock.unLock(); } public void signalB(){ lock.lock(); conditionB.signalAll(); lock.unLock(); } }
調用conditionB的signalAll方法只有ConditionB的waiting線程被喚醒,而不會喚醒conditionAl的waiting線程。
公平鎖與非公平鎖
公平鎖表示線程獲取鎖的順序是按照線程加鎖的順序來分配的,即按照先進先出的順序。打印結果基本有序。
非公平鎖就是一種獲取鎖的搶佔機制,是隨機得到鎖的,某些線程可能一直都拿不到鎖。打印結果基本亂序。默認的
Lock lock = new ReentrantLock(true); //公平鎖
Lock lock = new ReentrantLock(false); //非公平鎖
使用ReentrantReadWriteLock類
ReentrantLock類具備徹底互斥排他的效果,即同一個時間內只有一個線程在執行lock方法後面的任務。這樣的效率極低。因此JDK中提供了一種ReentrantReadWriteLock類,在某些不須要操做實例變量的方法中,能夠提升代碼執行速度。
讀寫鎖有兩個鎖,一個是讀操做相關的鎖,稱爲共享鎖;另外一個是寫操做相關的鎖,稱爲排它鎖。多個讀鎖之間不互斥,讀鎖和寫鎖互斥,寫鎖和寫鎖互斥。在沒有線程進行寫入操做時,進行讀操做的多個線程均可以獲取鎖,而進行寫操做的線程只有在獲取寫鎖以後才能進行寫入操做。即多個線程能夠同時進行讀取操做,可是同一個時刻只容許一個線程進行寫操做。
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
lock.writeLock().lock();