java多執行緒之同步鎖(Lock)
阿新 • • 發佈:2019-01-05
從Java5開始,提供了Lock, Lock提供了比synchronized方法和synchronized程式碼塊更廣泛的鎖定操作,Lock可以實現更靈活的結構,並且支援多個相關的Condition物件(物件監視器)。
Lock是控制多個執行緒對共享資源進行訪問的工具。通常,鎖提供了對共享資源的獨佔訪問,每次只能有一個執行緒對Lock物件加鎖,執行緒開始訪問共享資源之前應先獲得Lock物件。
示例程式碼:
ReentrantLockTest類:
public class ReentrantLockTest { private final ReentrantLock lock = new ReentrantLock(); //建立10個執行緒 public void userPrint() { for (int i = 0; i < 10; i++) { new Thread(new Runnable() { public void run() { print(); } }).start(); } } public void print() { lock.lock(); System.out.println("執行緒" + Thread.currentThread().getName() + "正在使用印表機"); try { Thread.sleep(new Random().nextInt(1000)); System.out.println("執行緒" + Thread.currentThread().getName() + "資源使用印表機"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //獲取等待得到同步鎖的執行緒個數 System.out.println("還剩 " + lock.getQueueLength() + "人要使用印表機"); lock.unlock(); } }
Main類:
public class Main {
public static void main(String[] args) throws Exception {
new ReentrantLockTest().userPrint();
}
測試結果:
可以看到我們建立的10個執行緒並沒有同時進來使用印表機方法,而是每次至進入一個執行緒使用印表機。
Lock操作多個Condition物件:
例項程式碼:
ReentrantLockTest類:
public class ReentrantLockTest { private final ReentrantLock lock = new ReentrantLock(); private Condition conditionA = lock.newCondition(); private Condition conditionB = lock.newCondition(); public void waitA() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "等待條件"); conditionA.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } lock.unlock(); } public void waitB() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "等待條件(沒有人喚醒我,我將一直等待..)"); conditionB.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } lock.unlock(); } public void signal() throws InterruptedException { lock.lock(); Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "執行完畢,喚醒A"); conditionA.signal(); lock.unlock(); } public void condition() throws InterruptedException { new Thread(new Runnable() { public void run() { waitA(); } }).start(); new Thread(new Runnable() { public void run() { waitB(); } }).start(); new Thread(new Runnable() { public void run() { try { signal(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); } }
Mian類:
public class Main {
public static void main(String[] args) throws Exception {
new ReentrantLockTest().condition();
}
測試結果:
上例中,我們可以看到我們建立了兩個Condition物件,並且啟動了三個執行緒,waitA和waitB方法都在其中一個執行緒執行,但是signal方法只喚醒了持有ConditionA的方法,而另一個waitB方法將一直等待被喚醒。使用Condition可以進行執行緒間的通訊。