JAVA并发-为现有的线程安全类添加原子方法
JAVA中有許多線程安全的基礎模塊類,一般情況下,這些基礎模塊類能滿足我們需要的所有操作,但更多時候,他們并不能滿足我們所有的需要。此時,我們需要想辦法在不破壞已有的線程安全類的基礎上添加一個新的原子操作。有如下4中方案:?
1 修改類的源碼,以添加新的原子操作?
2 繼承該線程安全類,并添加原子操作?
3 使用客戶端加鎖方式?
4 使用組合方式(推薦)?
一般來講,修改源碼的方式不太可行,這樣會破壞原有類的封裝性而且有些時候,源碼不可獲得。我們從第二種方式開始舉例:?
假設現在對于類Vector,我們知道它是線程安全類。如果想為他添加一個“若沒有則添加”方法,可是如下進行:?
我們來分析上面的代碼:使用ImprovedVector類對象的內置鎖,保證了contains()和add()方法的原子性,由于ImprovedVector類對象的內置鎖也就是Vector類對象的內置鎖(即add()方法和contains()方法的鎖),這樣有保證了add()方法和contains()方法的可見性,可以達到預期效果。?
第三種方法舉例:?
上面的例子是一個錯誤的例子,我們來分析下:首先,synchronized保證了list.contains()方法和list.add()方法的原子性,假設現在有一個類對象在執行putIfAbsent()方法,而且即將執行(還沒執行)list.add(2)方法,此時,有另外一個線程搶先執行了list.add(2)方法,該線程執行完畢之后,釋放了list的鎖,接著即將執行(還沒執行)list.add(2)方法開始得到CPU并執行。瞧,這個過程中,數字2被添加了2次。就是說,上面的代碼中僅僅保證了contains()方法和add()方法的原子性,以及對對list引用操作的互斥性,并沒有保證list.add()方法的可見性。?
仔細想想,問題出在putIfAbsent()方法的鎖與list對象的鎖不是同一個,putIfAbsent()方法的鎖是ImprovedList類的鎖,而list.add()方法的鎖是Collections.synchronizedList()使用的鎖,因此將上面的代碼改成:?
第四種方法舉例:?
乍一看發現,上面的代碼在安全性方面好像弱了好多, putIfAbsent(T x)方法中的fianl變量list可能連線程安全類都不是,但是對于上面的代碼,我們有個假設(當某個鏈表對象在傳遞給ImprovedList的構造函數之后,客戶代碼再也不會使用這個對象,而是使用與其對應的ImprovedList對象),有了這個假設前提,上面的代碼就是線程安全的了。?
上面就是JAVA并發編程中,在一個已有的線程安全類的基礎上添加同步函數的4個方法。?
本文轉自農夫山泉別墅博客園博客,原文鏈接:http://www.cnblogs.com/yaowen/p/6294808.html,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的JAVA并发-为现有的线程安全类添加原子方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 虚拟路由器冗余协议(VRRP)原理与实验
- 下一篇: AI 学习之路——轻松初探 Python