Lock & Condition

Synchronized同步塊的不足

      在多線程環境下保證線程同步的方法大多是使用synchronized關鍵字,但是這個關鍵字在某些環境下是很死板的。其主要缺點如下:

     (1)如果一個線程已經在一個synchronized塊中執行,另一個線程視圖進入這個同步塊,那麼它必須等待直到當前佔用這那個同步塊的線程執行完並退出。如果線程一直沒有進入同步塊,那麼那個等待的線程就一直處於阻塞狀態並且不能被interrupted!。

     (2)當一個線程執行完同步塊代碼並退出後,任何一個等待進入的線程都可以獲得鎖去執行同步塊代碼,也就是說,有的線程可能一直沒有機會獲取這個機會去執行同步塊,也就是有可能會被餓死!。
     (3)Synchronized塊沒有任何方法去查詢那些爲使用特殊資源而等待的線程的狀態。

     (4)Synchronized塊必須在相同的方法裏出現,也就是說一個同步塊不能在一個方法裏開始,在另一個方法裏結束。

Lock和Condition的基本應用

    基於以上考慮,很多不適合Synchronized的場合可以使用Lock來解決!以下貼出基本的使用源碼:

public class LockMain {
	//創建一把鎖
	static Lock lock = new ReentrantLock();
	// 創建第一個條件,B會用此條件等待,A會用此條件通知B開始任務
	static Condition conditionA = lock.newCondition();
	// 創建第二個個條件,C會用此條件等待,B會用此條件通知C開始任務
	static Condition conditionB = lock.newCondition();

	public static void main(String[] args) {
		PersonA a = new PersonA();
		PersonB b = new PersonB();
		PersonC c = new PersonC();
		// 爲了證實執行的順序是A、B、C,這裏特意先倒着開啓任務
		new Thread(c).start();
		new Thread(b).start();
		new Thread(a).start();
	}

	/**
	 * 第一個人
	 * 
	 * @author Administrator
	 * 
	 */
	public static class PersonA implements Runnable {
		public void run() {
			lock.lock();
			try {
				// 模擬等待時間
				Thread.sleep(3000);
				// 辦理完後業務員會通知下一個人
				System.out.println("A開始辦理...");
				System.out.println("A辦理完畢,請下一位B到3號窗口");
				conditionA.signal();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				// 用完之後記得釋放鎖,不然別人還是不能使用這個鎖
			} finally {
				// 一定要釋放鎖
				lock.unlock();
			}
		}
	}

	/**
	 * 第二個人
	 * 
	 * @author Administrator
	 * 
	 */
	public static class PersonB implements Runnable {

		public void run() {
			lock.lock();
			try {
				// B只有等A辦理完了才能繼續辦
				conditionA.await();
				System.out.println("B開始辦理...");
				System.out.println("B辦理完畢,請下一位C到3號窗口");
				conditionB.signal();
				// 辦理完後業務員會通知下一個人
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}

	/**
	 * 第三個人
	 * 
	 * @author Administrator
	 * 
	 */
	public static class PersonC implements Runnable {

		public void run() {
			lock.lock();
			try {
				// B只有等A辦理完了才能繼續辦
				conditionB.await();
				System.out.println("C開始辦理...");
				System.out.println("C辦理完畢,準備下班吧");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}
}

     其用法就是辣麼簡單,我們再看下執行結果,是不是按照A、B、C的順序來的:

   

      截圖已證實Lock和Condition的作用。下面我們開始一步步揭開Lock的神祕面紗。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章