2010/01/13

Java Concurrency(8)

同步

Threads主要地溝通透過分享連接到欄位以及物件參考所參考的欄位,這種形式的溝通非常的有效率,但是造成了兩種
錯誤可能:thread interference以及memory consistency errors. 用來防止這樣問題的工具稱作synchronization

Thread Interference

假設一個簡單的class稱作Counter
class Counter {
    private int c = 0;

    public void increment() {
        c++;
    }

    public void decrement() {
        c--;
    }

    public int value() {
        return c;
    }

}

Counter被設計成每次引發increment就會把c加1,而每次引發decrement將會從c減1,然而如果一個Counter物件
被多重trheads所參考, interference介於threads將會阻礙我們所期望得到的結果

Interference發生在兩種操作上,執行在不同的threads但是用相同的資料, interleave,這代表兩個操作包含了
多個步驟和連續的重疊步驟。

對Counter實例而言這也許不太可能發生interleave當所有對c的operations都是單一的,單純的敘述。然而甚至
基本的敘述也可能被虛擬機器解釋成多個步驟,我們不會檢驗虛擬機器所做的特定步驟,我們足以知道簡單的運算式c++
可以被拆成三個步驟

1. 取得c目前的值
2. 給取得的值增加1
3. 存放增加後的值到c

運算式c--也可以被拆解成相同的方法,除了第二個步驟有可能是減法以外。

假設Thread A引發increment幾乎在同時Thread B也引發了decrement,如果c的初始值是0,它們的interleaved
表現可能會是下列的順序:

1. Thread A: 取得c
2. Thread B: 取得c
3. Thread A: 給取得值增加1,結果為1
4. Thread B: 給取得值減少1,結果為-1
5. Thread A: 儲存結果到c,c成為1
6. Thread B: 儲存結果到c,c成為-1

Thread A的結果就遺失掉了,被Thread B複寫了,這只是其中一種interleave的可能,在很多不同的情況下可能會是
Thread B的結果遺失,或是不會有任何錯誤,因為這是無法預測的,thread interference的bugs可以是非常難以偵
測及修復的。

我們想要的步驟應該要是:

1. Thread A: 取得c
2. Thread A: 給取得值增加1,結果為1
3. Thread A: 儲存結果到c,c成為1
4. Thread B: 取得c
5. Thread B: 給取得值減少1,結果為0
6. Thread B: 儲存結果到c,c成為0

這樣一來才能夠確保每次有Thread來更動c值時可以讓c值是正確的,等回我們會介紹如何同步c的數值。

參考網址
http://java.sun.com/docs/books/tutorial/essential/concurrency/interfere.html

No comments:

Post a Comment