MartinYeung
MartinYeung

Love life Love IT IT blog: https://ithelp.ithome.com.tw/users/20119569

Java - Thread-Safety是什麼 – Part 2

閱讀時間: 10分鐘

接上一篇文章,又來為大家在10分鐘內講解一些有關Thread-safety的介紹。

再講3個做到Thread-safety的方式。

大家可以因應情況選擇一個最合適的表達方法。

4. Synchronized Collections

大家可以輕易地創建一個thread-safe的集合(collection)透過synchronization wrappers。

Collection<Integer> syncCollection = Collections.synchronizedCollection(new ArrayList<>());
Thread thread1 = new Thread(() -> syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)));
Thread thread2 = new Thread(() -> syncCollection.addAll(Arrays.asList(7, 8, 9, 10, 11, 12)));
thread1.start();
thread2.start();

synchronized collections 利用內在鎖(intrinsic locking)在每一個method中.

換言之,method在同一時間只可以被一個thread存取,

假如其他threads試圖存取,就會被阻擋blocked,直到那個method被上一個thread 解鎖(unlocked)。

5. Concurrent Collections

它是synchronized collections的替代品,同樣可以做到thread-safe 的集合。

在Java中, 提供了一個java.util.concurrent package,裡內有幾個concurrent collections 例如: ConcurrentHashMap。

Map<String,String> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put("1", "one");
concurrentMap.put("2", "two");
concurrentMap.put("3", "three");

不過concurrent collections跟synchronized collections是有不同的地方,concurrent collections 會將數據分成不同部分以做到thread-safety的功能。

在ConcurrentHashMap,每一個thread可以鎖住一個map的segment(一個map由不同segments組成)。所以一個map可以同時被多個threads存取。

6. Atomic Objects

可以利用atomic classes來做到thread-safety的功能,Java可以提供AtomicInteger, AtomicLong, AtomicBoolean, 和AtomicReference等元素來完成任務。

首先,Atomic classes可以容許大家完成各種atomic的操作以做到thread-safe,同時沒有用到任何synchronization。

會用以下例子詳細講解:

public class Counter {
     
    private int counter = 0;
     
    public void incrementCounter() {
        counter += 1;
    }
     
    public int getCounter() {
        return counter;
    }
}

假設目前的是一個race condition,兩個threads同時存取incrementCounter() method。最後的結果是counter field的值會是2,而當中的incrementCounter()不是atomic。

下面會是一個thread-safe的例子透過利用物件AtomicInteger修改了Counter class:

public class AtomicCounter {
     
    private final AtomicInteger counter = new AtomicInteger();
     
    public void incrementCounter() {
        counter.incrementAndGet();
    }
     
    public int getCounter() {
        return counter.get();
    }
}

這個例子是thread-safe是因為它在增加數值時利用了atomic的元素- incrementAndGet,先加1再存取加1之後的值。


CC BY-NC-ND 2.0 版权声明

喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。

加载中…

发布评论