1.共享變量的可見性問題
在讀寫操作同步進行時,寫操作對共享變量進行的改變沒有應(yīng)用到讀操作,這時我們稱寫操作對讀操作不可見。
2.什么是原子性
對于一些系列操作,要么執(zhí)行完,要么不執(zhí)行,則稱這一系列操作具有原子性
3.什么是CAS
compareAndSet,比較內(nèi)存位置的變量是否是舊的預(yù)期值,如果是則使用新的值替換,這是處理器的一個原子性操作
4.什么是AQS
AQS維護了一個state變量類存放狀態(tài)信息,對于ReenTrantLock,開說,state表示可以可重入鎖的次數(shù)
5.什么是可重入鎖
在獲取被自己線程占用的鎖時,不被阻塞,則是可重入鎖,synchronized是強制性的內(nèi)置鎖,屬于可重入鎖;
可重入鎖的原理: 在鎖內(nèi)部維護了一個線程標(biāo)識和一個計數(shù)器,標(biāo)識表示當(dāng)前被哪個線程占用,如果是當(dāng)前線程,
則獲取到鎖并計數(shù)器+1,當(dāng)釋放鎖后計數(shù)器-1,當(dāng)計算器為0時候,現(xiàn)成標(biāo)示重置為null,阻塞線程將被喚醒。
6.Synchronized鎖的缺點
同一時間只能有一個線程訪問共享變量,無法實現(xiàn)同步讀操作
7.ReenTrantReadWriteLock的概念和原理
可以實現(xiàn)讀寫分離,多個讀操作可以同時讀取,但最多只有一個寫線程存在。
如果已經(jīng)有一個線程獲取了讀鎖,這個時候要想獲取寫鎖,則需要等待讀鎖釋放;如果已經(jīng)有一個線程獲取了寫鎖,則
所有獲取讀鎖的線程都要等待寫鎖被釋放。
8.volatile變量
當(dāng)線程寫入的時候會把寄存器或者其他地方,當(dāng)線程讀取時會從主內(nèi)存中獲取最新值,而非在當(dāng)前線程的私有內(nèi)存或緩存中獲取。
Java5之后,JVM實現(xiàn)了在對volatile的保證:對volatile域的寫入操作happens-before于每一個后續(xù)的同一個域的讀寫操作。
9.樂觀鎖和悲觀鎖、獨占鎖和共享鎖、公平鎖和非公平鎖
悲觀鎖,使用只能有一個線程占用,通常依靠數(shù)據(jù)庫的鎖機制;樂觀鎖,只會數(shù)據(jù)更新的時候檢測compareAndSet。
獨占鎖,獨占資源的互斥鎖。共享鎖,允許同時有多個讀線程,但最多只有一個寫線程,讀和寫是互斥的。
公平鎖,阻塞的線程在獲取鎖時,采用FIFO先進先出的策略。非公平鎖,在鎖釋放后,多個線程,根據(jù)線程調(diào)度策略去獲取鎖;
ReenTrantLock是獨占鎖,也是悲觀鎖。ReadWriteLock是共享鎖,也是悲觀鎖。ReenTrantLcok和ReadWriteLock都提供了公平鎖和非公平鎖的實現(xiàn)
new ReenTrantLock(true/false) true為公平鎖,false為非公平鎖,不傳參數(shù)默認(rèn)為非公平鎖;
公平鎖比非公平鎖要更消耗資源
10.ConcureentHashMap原理 參考http://www.importnew.com/21781.html
ConcureentHashMap使用分離鎖,分段segment,每個segments繼承了ReenTrantLock,使用了ReenTrantLock的獨占鎖來控制同一段只能有一個線程進行寫。
而value采用volatile語義,讀操作直接從主內(nèi)存中獲取,不需要加鎖。
get方法: 先根據(jù)Hash算法,算出key的Hash值,根據(jù)Hash值來確定value存放在哪個segment中;在當(dāng)前segment中找到對應(yīng)的entry,在獲取到后判斷是否是完整
對象,如果不完整有可能是在獲取的過程中插入了put了一個剛好需要get的entry,但是還沒有構(gòu)建完成,就再用鎖的方式獲取一次,等待寫鎖釋放后再讀取。segment
中計數(shù)entry的count值和entry中的value值都是volatile域的,所以在獲取的時候都是最新值。
public V get(Object key) {
int hash = hash(key); // throws NullPointerException if key null
return segmentFor(hash).get(key, hash);
}
V get(Object key, int hash) {
if (count != 0) { // read-volatile // ①
HashEntry<K,V> e = getFirst(hash);
while (e != null) {
if (e.hash == hash && key.equals(e.key)) {
V v = e.value;
if (v != null) // ② 注意這里
return v;
return readValueUnderLock(e); // recheck
}
e = e.next;
}
}
return null;
}
static final class HashEntry<K,V> {
final K key;
final int hash;
volatile V value;
final HashEntry<K,V> next;
。。。
}
put方法和remove方法:采用ReenTranLock獨占鎖進行寫操作