并發的學習與使用
通過單例模式理解synchronized,volatile
上兩篇主要是常見的關于并發的一些知識,本篇將介紹一些自己平常不常用的一些并發相關的內容。
單例模式的一種新的方式
最近在讀RxJava的源碼時,見到了一種新的單例模式,可能是自己見識太少,之前對這種方式真的沒見過,也可以說聞所未聞。由此引發了一些對Atomic**相關原子類的思考的研究,先看代碼:
public class Singleton {
private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();
private Singleton (){}
public static Singleton getInstance() {
for (;;) {
Singleton current = INSTANCE.get();
if (current != null) {
return current;
}
current = new Singleton();
if (INSTANCE.compareAndSet(null, current)) {
return current;
}
}
}
}
先看下AtomicReference的源碼:
只貼出主要涉及部分.png
AtomicReference是作用是對"對象"進行原子操作。通過源碼可以看出,它是通過"volatile"和"Unsafe提供的CAS(比較與交換,Compare and swap,是一種有名的無鎖算法函數)實現原子操作。
- current是volatile類型。這保證了:當某線程修改value的值時,其他線程看到的value值都是最新的value值,即修改之后的volatile的值。
- 通過CAS設置value。這保證了:當某線程池通過CAS函數(如compareAndSet函數)設置value時,它的操作是原子的,即線程在操作value時不會被中斷。CAS是一種無阻塞的鎖,采用不斷比較設值的方式來避免并發問題,不會有鎖的等待和上下文切換問題,性能消耗較小。
如果當前值 == 預期值,則以原子方式將該值設置為給定的更新值。
這種方式既能夠保證延遲加載又能保證原子性及實例的唯一性,代碼也相對比較簡潔。
通過并發的學習與使用,線程的阻塞和上下文的切換會帶來一定的性能開銷,尤其在高并發的環境下。
而原子變量可以避免優先級倒置和死鎖等危險,競爭比較便宜,協調發生在更細的粒度級別,允許更高程度的并行機制等等