Posted on 2010-01-14 14:36
瘋狂 閱讀(1098)
評論(0) 編輯 收藏 所屬分類:
java
為了確??梢栽诰€程之間以受控方式共享數(shù)據(jù),Java 語言提供了兩個關(guān)鍵字:synchronized
和 volatile
。
Synchronized
有兩個重要含義:它確保了一次只有一個線程可以執(zhí)行代碼的受保護(hù)部分(互斥,mutual exclusion 或者說 mutex),而且它確保了一個線程更改的數(shù)據(jù)對于其它線程是可見的(更改的可見性)。
如果沒有同步,數(shù)據(jù)很容易就處于不一致狀態(tài)。例如,如果一個線程正在更新兩個相關(guān)值(比如,粒子的位置和速率),而另一個線程正在讀取這兩個值,有可能在第一個線程只寫了一個值,還沒有寫另一個值的時候,調(diào)度第二個線程運(yùn)行,這樣它就會看到一個舊值和一個新值。同步讓我們可以定義必須原子地運(yùn)行的代碼塊,這樣對于其他線程而言,它們要么都執(zhí)行,要么都不執(zhí)行。
同步的原子執(zhí)行或互斥方面類似于其它操作環(huán)境中的臨界段的概念。
同步可以讓我們確保線程看到一致的內(nèi)存視圖。
處理器可以使用高速緩存加速對內(nèi)存的訪問(或者編譯器可以將值存儲到寄存器中以便進(jìn)行更快的訪問)。在一些多處理器體系結(jié)構(gòu)上,如果在一個處理器的高速緩存中修改了內(nèi)存位置,沒有必要讓其它處理器看到這一修改,直到刷新了寫入器的高速緩存并且使讀取器的高速緩存無效。
這表示在這樣的系統(tǒng)上,對于同一變量,在兩個不同處理器上執(zhí)行的兩個線程可能會看到兩個不同的值!這聽起來很嚇人,但它卻很常見。它只是表示在訪問其它線程使用或修改的數(shù)據(jù)時,必須遵循某些規(guī)則。
Volatile
比同步更簡單,只適合于控制對基本變量(整數(shù)、布爾變量等)的單個實(shí)例的訪問。當(dāng)一個變量被聲明成 volatile
,任何對該變量的寫操作都會繞過高速緩存,直接寫入主內(nèi)存,而任何對該變量的讀取也都繞過高速緩存,直接取自主內(nèi)存。這表示所有線程在任何時候看到的 volatile
變量值都相同。
如果沒有正確的同步,線程可能會看到舊的變量值,或者引起其它形式的數(shù)據(jù)損壞。
使用 synchronized
塊可以讓您將一組相關(guān)更新作為一個集合來執(zhí)行,而不必?fù)?dān)心其它線程中斷或看到計算的中間結(jié)果。以下示例代碼將打印“1 0”或“0 1”。如果沒有同步,它還會打印“1 1”(或“0 0”,隨便您信不信)。
public class SyncExample {
private static lockObject = new Object();
private static class Thread1 extends Thread {
public void run() {
synchronized (lockObject) {
x = y = 0;
System.out.println(x);
}
}
}
private static class Thread2 extends Thread {
public void run() {
synchronized (lockObject) {
x = y = 1;
System.out.println(y);
}
}
}
public static void main(String[] args) {
new Thread1().run();
new Thread2().run();
}
}
在這兩個線程中都必須使用同步,以便使這個程序正確工作。
Volatile
對于確保每個線程看到最新的變量值非常有用,但有時我們需要保護(hù)比較大的代碼片段,如涉及更新多個變量的片段。
同步使用監(jiān)控器(monitor)或鎖的概念,以協(xié)調(diào)對特定代碼塊的訪問。
每個 Java 對象都有一個相關(guān)的鎖。同一時間只能有一個線程持有 Java 鎖。當(dāng)線程進(jìn)入 synchronized
代碼塊時,線程會阻塞并等待,直到鎖可用,當(dāng)它可用時,就會獲得這個鎖,然后執(zhí)行代碼塊。當(dāng)控制退出受保護(hù)的代碼塊時,即到達(dá)了代碼塊末尾或者拋出了沒有在 synchronized
塊中捕獲的異常時,它就會釋放該鎖。
這樣,每次只有一個線程可以執(zhí)行受給定監(jiān)控器保護(hù)的代碼塊。從其它線程的角度看,該代碼塊可以看作是原子的,它要么全部執(zhí)行,要么根本不執(zhí)行。