1、原始構成:
synchronized是關鍵字,屬於JVM層面,底層是由一對monitorenter和monitorexit指令實現的。
ReentrantLock是一個具體類,是API層面的鎖。
2、使用方法:
synchronized不需要用戶手動釋放鎖,當synchronized代碼塊執行完成后,系統會自動讓線程釋放對鎖的占用
ReentrantLock需要用戶手動釋放鎖,若沒有手動釋放可能導致死鎖現象。
3、等待是否可中斷:
synchronized不可中斷,除非拋出異常或者正常運行完成
ReentrantLock可中斷
4、加鎖是否公平:
synchronized非公平鎖
ReentrantLock兩者都可以,默認是非公平鎖。
5、鎖綁定多個條件Condition:
synchronized沒有。
ReentrantLock可用來分組喚醒需要喚醒的線程。而不是像synchronized要么隨機喚醒一個線程,要么喚醒所有線程。
題目:多線程之間按順序調用,實現A->B->C三個線程啟動,要求如下:
* AA打印5次,BB打印10次,CC打印15次
* 緊接着
* AA打印5次,BB打印10次,CC打印15次
* 來10輪
class ShareResource { private int number = 1; private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); public void print5() { lock.lock(); try { while (number != 1) { condition1.await(); } for (int i = 1; i <= 5; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } number = 2; condition2.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void print10() { lock.lock(); try { while (number != 2) { condition2.await(); } for (int i = 1; i <= 10; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } number = 3; condition3.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void print15() { lock.lock(); try { while (number != 3) { condition3.await(); } for (int i = 1; i <= 15; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } number = 1; condition1.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } public class SyncAndReentrantLockDemo { public static void main(String[] args) { ShareResource shareResource = new ShareResource(); new Thread(() -> { for (int i = 0; i < 10; i++) { shareResource.print5(); } }, "AAA").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { shareResource.print10(); } }, "BBB").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { shareResource.print15(); } }, "CCC").start(); } }