iT邦幫忙

0

[Java] Thread-Safety是什麼 - Part 3

閱讀時間: 10分鐘

接上一篇文章,又來為大家在10分鐘內講解一些有關Thread-safety的介紹。
再講多3個做到Thread-safety的方式。
大家可以因應情況選擇一個最合適的表達方法。

7. Synchronized Methods

在同一時間只有一個thread能存取synchronized method,
而其他threads會被阻擋直到第一個thread/之前的thread完成所以任務或者出現例外(exception)。
下面會是一個thread-safe的例子

public synchronized void incrementCounter() {
    counter += 1;
}

首先,在synchronized method的名字前必須有一個synchronized的關鍵字。有了synchronized method,
可以避免多個threads同時存取method。

synchronized method是依賴 內在鎖“intrinsic locks” 或監視鎖 “monitor locks”來完成它的功能。
intrinsic lock是一個與class中特定的實例有關的內在實體。
而在多個threads的環境中,monitor locks只是一個監視角色作為監測不包括的存取情況。
當一個thread使用synchronized method時,它就會獲得一個內在鎖(intrinsic locks)。
在完成了所有任務後,那個thread就會釋放內在鎖(intrinsic locks),允許其他threads來獲得這個內在鎖(intrinsic locks)以存取synchronized method。
大家可以實作同步化在instance methods, static methods 和 statements (synchronized statements)。

8. Synchronized Statements
有時候,當我們只是對於一個segment來進行thread-safe就會有機會出現問題。為了解決及預防,我們可以重新打造incrementCounter() method:

public void incrementCounter() {
    // additional unsynced operations
    synchronized(this) {
        counter += 1; 
    }
}

在method內有不同operations,有些要用synchronization,有些是不同的。
針對一些需要用到synchronization的地方,我們可以將那個部分放到synchronized block內。
與synchronized methods不同,synchronized statements必須具體指出物件,
而在這條件下,可以透過使用this reference來滿足。
由於Synchronization的成本高,所以運用了這個方法可以只針對method中的某一部份來做synchronize。

9. Volatile Fields
在一般class中, Class變量的值會被儲存在CPU。
不過由於這個情況會對變量的可見性受到影響,有可能會出現不被其他threads見到的情況。
為了預防這個情況,我們可以使用volatile關鍵字來定義變量。

public class Counter {
 
    private volatile int counter;
 
    // standard constructors / getter
     
}

運用了volatile關鍵字,可以將變量的值直接儲存在主記憶體內。以上的例子就是把counter儲存在主記憶體內。所以當執行這個程序時,它會直接去主記憶體查找而不是在CPU的cache內。而每一次JVM在寫入counter的值時都會直接寫進主記憶體內。
而且運用了volatile關鍵字,可以讓其他thread都能夠在主記憶體內見到所有變量的值。
下面會是一個例子解釋:

public class User {
 
    private String name;
    private volatile int age;
 
    // standard constructors / getters
     
}

每次JVM都會把變量age寫進主記憶體內,但同一時間也會將變量name寫進主記憶體內。因此,這也保證了所有變量的值都會儲存在主記憶體。也可以確保所有threads都能在主記憶體內見到它們的值。


尚未有邦友留言

立即登入留言