顯示鎖ReentrantLock和Condition的使用
阿新 • • 發佈:2018-12-18
一、ReentrantLock
(1)、java.util.concurrent.locks包中的ReentrantLock就是重入鎖,它實現了Lock介面,Lock加鎖和解鎖都是顯示的。ReentrantLock重入鎖可以實現synchronized關鍵字的功能。
主要方法:
lock:獲得鎖。
unlock:釋放鎖。
(2)、java對synchronized優化之後,ReentrantLock和synchronize大的區別:
a、鎖的粒度,ReentrantLock更細,更靈活。
b、ReentrantLock可以指定鎖的公平性。synchronize只能是非公平的。
c、ReentrantLock可以利用Condition(條件)類選擇性分組喚醒執行緒。
d、ReentrantLock可以中斷一個正在等待獲取鎖的執行緒。lockInterruptibly()。
(3)、典型的使用格式:
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } }
測試i++的程式碼:
注意:必須在finally塊中呼叫unlock語句釋放鎖,以確保即使在方法體中丟擲異常(try塊)鎖也會釋放鎖。否則這個鎖永遠不釋放。
/** * @author tangquanbin * @date 2018/12/16 22:24 */ public class ReentrantLockService{ private Lock lock = new ReentrantLock(); private int count = 0; public void getCount(){ try { //獲得鎖 lock.lock(); System.out.println("thread :"+Thread.currentThread().getName()+" count = "+count++); } catch (Exception e) { e.printStackTrace(); }finally { //在finally塊中呼叫unlock語句,以確保即使在方法體中丟擲異常(try塊)也會釋放鎖。 lock.unlock(); } } public static void main(String[] args) { ReentrantLockService service = new ReentrantLockService(); for(int i=0; i<100; i++){ new Thread("" + i){ @Override public void run(){ service.getCount(); } }.start(); } } }
二、Condition
(1)、Condition通過Lock物件呼叫newCondition()方法獲得。藉助Lock,Condition可以實現wait && notify同樣的功能。主要方法:
await(): 使當前執行緒等待
signal():喚醒一個等待的執行緒
signalAll():喚醒所有等待的執行緒
(2)、在使用Condition的方法時需要先獲得鎖,即呼叫Lock物件的lock()方法,否則會丟擲IllegalMonitorStateException,因為沒有監視器物件。
Condition使用例項:
/** * @author tangquanbin * @date 2018/12/18 21:14 */ public class ConditionService { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void awaitTest(){ try { lock.lock(); System.out.println("before await()"); condition.await(); System.out.println("after await()"); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public void signalTest(){ try { lock.lock(); System.out.println("before signal()"); condition.signal(); System.out.println("after signal()"); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public static void main(String[] args) { ConditionService service = new ConditionService(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { service.awaitTest(); } }); thread1.start(); Thread thread2 = new Thread(new Runnable() { @Override public void run() { service.signalTest(); } }); thread2.start(); } }