標籤:
1. synchronized的作用
synchronized類似於win32中的臨界區,臨界區的作用:對於共用的全域變數,在多個線程並發的情況下,對這樣的全域變數的讀寫就會發生讀寫的衝突,
使得全域變數的讀寫,能夠以原子的方式被執行,而不是一個線程要讀取全域資料時候,由於線程調度,而另一個線程則此時被喚醒,改變了這個全域變數的值,
這樣使得讀取的線程獲得的資料不穩定,所以對於全域變數的讀寫的代碼,我們要使用臨界區使得這些代碼原子化,此時只要在臨界區中的代碼,就會以原子方式執行,
而不會由於線程調度被中斷,也就保證了全域共用資源的互斥訪問。例如:
CRITICAL_SECTION CriticalSection; // 臨界區對象
1 DWORD WINAPI WriteThreadProc( LPVOID lpParameter ) 2 { 3 // 進入臨界區 4 EnterCriticalSection(&CriticalSection); 5 // 寫資源 6 g_data = 123;7 // 離開臨界區8 LeaveCriticalSection(&CriticalSection); 9 }
DWORD WINAPI ReadThreadProc( LPVOID lpParameter ) { // 進入臨界區 EnterCriticalSection(&CriticalSection); // 讀資源 printf(g_data); // 離開臨界區 LeaveCriticalSection(&CriticalSection); }
上面的例子中的在臨界區中,進行資料讀寫,就不會發生共用資源衝突。類似的,在java中使用 synchronized 關鍵字來實現臨界區代碼塊。
關於的synchronized 使用方法,參考:Java synchronized詳解
2. java.lang.notify 方法
每一個對象都有一個所謂的 object‘s monitor(對象監視器)。假設其為:obj.monitor。能夠獲得obj對象的引用的線程都可以通過 obj.wait() 方法在這個對象監視器(obj.monitor)上註冊一個監聽。這樣所有調用 obj.wait的線程都將添加到,對象的類似等待隊列中。
JDK文檔翻譯:
喚醒在此對象監視器上等待的單個線程。如果有多個線程都在此對象上等待(也就是線程中執行了 obj.wait),則會選擇喚醒其中一個線程。選擇是任意性(隨機的)的,並在對實現做出決定時發生。線程通過調用其中一個 wait 方法,在對象的監視器上等待。
直到當前線程放棄此對象上的鎖定,才能繼續執行被喚醒的線程。被喚醒的線程將以常規方式與在該對象上主動同步的其他所有線程進行競爭;例如,喚醒的線程在作為鎖定此對象的下一個線程方面沒有可靠的特權或劣勢。
此方法只應由作為此對象監視器的所有者的線程來調用。通過以下三種方法之一,線程可以成為此對象監視器(obj.monitor)的所有者:
- 通過執行此對象的同步執行個體方法。(也就是方法簽名上有
synchronized 關鍵字的執行個體方法,也就是執行 obj.instanceMethod ,並且這個方法有synchronized 修飾)
- 通過執行在此對象上進行同步的
synchronized 語句的本文。(synchronized代碼塊, 也就是 synchronized(obj){obj.wait();} 這樣這個代碼塊中就具有了 obj.monitor,就可以調用 obj.wait 了)
- 對於
Class 類型的對象,可以通過執行該類的同步靜態方法。(也就是方法簽名上有 synchronized 關鍵字的執行個體方法,也即類級方法,也就是obj.staticMehtod,並且這個方法的簽名有synchronized 關鍵詞修飾)
一次只能有一個線程擁有對象的監視器。
在上面三種情況下,線程就擁有了對象監視器(obj.monitor)則就可以在其中調用 obj.notify 方法了。
線程可以成為此對象監視器(obj.monitor)的所有者:的第一種情況 同步對象就是 this 當前的執行個體對象。所以在這個執行個體方法中就可以這樣調用:this.notify();
第三種情況下,其實也就是同步對象就是 ThreadTest.class.wait(); 也就是在類對象上調用 notify 方法。
第二種情況下,由於我們可以手動的指定指定我們要獲得的監視器的對象,此時就不僅僅是 this 和 ClassName.class 這兩個對象了,可以是其他的任何對象,例如 waitObj 這個對象對所有線程都可見,專門用來協調多線程並發的情況。
java.lang.Object 的 wait 和 notify方法,及關鍵字 synchronized的作用