多執行緒問題volatile Synchronise Lock and AtomicReference
以前用到的關於鎖和執行緒安全注意的地方比較少,最近專案出現一些公用內容需保證執行緒安全所以採用AtomicReference 和concurrentMap,
順便再梳理了下執行緒安全的內容:
從效能上來說AtomicReference比synochronizd 和Lock要好得多。
下面來看下一些實現:
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTask implements Runnable { private int lockVariable; private Lock lock; public LockTask() { this.lockVariable = 0; this.lock = new ReentrantLock(); } @Override public void run() { for (int i = 0; i < 1000000000; i++) { lock.lock(); lockVariable = i; lock.unlock(); } } }
public class SecuritySingleton { private static SecuritySingleton securitySingleton; private SecuritySingleton(){}; static synchronized SecuritySingleton getInstance(){ if(securitySingleton==null){ securitySingleton = new SecuritySingleton(); } return securitySingleton; } }
import java.util.concurrent.atomic.AtomicInteger; public class AtomicTask implements Runnable { private final AtomicInteger variableInt; public AtomicTask() { this.variableInt = new AtomicInteger(0); } @Override public void run() { for (int i = 0; i < 1000000000; i++) { variableInt.set(1); } } }
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; public class AtomicService { private final AtomicReference<Map<String, String>> areaMapping = new AtomicReference<>(); private AtomicService() { this.areaMapping.set(new ConcurrentHashMap()); } public void addValue(String key, String value) { areaMapping.get().put(key, value); } public String getValue(String key) { return areaMapping.get().get(key); } }
摘抄自部落格:https://www.cnblogs.com/caiba/p/10616615.html
synochronizd和volatile關鍵字區別:
1. volatile關鍵字解決的是變數在多個執行緒之間的可見性;而sychronized關鍵字解決的是多個執行緒之間訪問共享資源的同步性。
2. volatile只能用於修飾變數,而synchronized可以修飾方法,以及程式碼塊。(volatile是執行緒同步的輕量級實現,所以volatile效能比synchronized要好,並且隨著JDK新版本的釋出,sychronized關鍵字在執行上得到很大的提升,在開發中使用synchronized關鍵字的比率還是比較大)
3. 多執行緒訪問volatile不會發生阻塞,而sychronized會出現阻塞。
4. volatile能保證變數在多個執行緒之間的可見性,但不能保證原子性;而sychronized可以保證原子性,也可以間接保證可見性,因為它會將私有記憶體和公有記憶體中的資料做同步。
執行緒安全包含原子性和可見性兩個方面。
對於用volatile修飾的變數,JVM虛擬機器只是保證從主記憶體載入到執行緒工作記憶體的值是最新的。
一句話說明volatile的作用:實現變數在多個執行緒之間的可見性。
synchronized和lock區別
1)Lock是一個介面,而synchronized是Java中的關鍵字,synchronized是內建的語言實現;
2)synchronized在發生異常時,會自動釋放執行緒佔有的鎖,因此不會導致死鎖現象發生;而Lock在發生異常時,如果沒有主動通過unLock()去釋放鎖,則很可能造成死鎖現象,因此使用Lock時需要在finally塊中釋放鎖;
3)Lock可以讓等待鎖的執行緒響應中斷,而synchronized卻不行,使用synchronized時,等待的執行緒會一直等待下去,不能夠響應中斷;
4)通過Lock可以知道有沒有成功獲取鎖,而synchronized卻無法辦到。
5)Lock可以提高多個執行緒進行讀操作的效率(讀寫鎖)。
在效能上來說,如果競爭資源不激烈,兩者的效能是差不多的,而當競爭資源非常激烈時(即有大量執行緒同時競爭),此時Lock的效能要遠遠優於synchronized。所以說,在具體使用時要根據適當情況選擇。