o2o網(wǎng)站建設(shè)最好公司seo研究中心qq群
1.1 常見(jiàn)的鎖策略
-
預(yù)測(cè)鎖衝突概率
-
樂(lè)觀鎖:加鎖的時(shí)候,假設(shè)出現(xiàn)鎖衝突的概率不大。圍繞加鎖做的工作會(huì)更少。
-
悲觀鎖:加鎖的時(shí)候,假設(shè)鎖出現(xiàn)衝突的概率很大。圍繞加鎖做的工作會(huì)更多。
-
synchronized “自適應(yīng)” 初始是樂(lè)觀的。鎖衝突達(dá)到一定程度就會(huì)轉(zhuǎn)變爲(wèi)悲觀的。
-
加鎖開(kāi)銷(xiāo)(時(shí)間開(kāi)銷(xiāo))
-
重量級(jí)鎖
-
輕量級(jí)鎖
-
掛起等待鎖:悲觀鎖/重量級(jí)鎖的一種典型實(shí)現(xiàn)。讓出cpu資源,過(guò)一段時(shí)間通過(guò)其他途徑得知,再伺機(jī)而動(dòng)。
-
自旋鎖:樂(lè)觀鎖/輕量級(jí)鎖的一種典型實(shí)現(xiàn)。忙等,等待過(guò)程中不釋放cpu資源,反復(fù)檢測(cè)鎖是否被釋放。一旦釋放立即有機(jī)會(huì)獲取到鎖。
-
公平鎖:先來(lái)後到
-
非公平鎖:synchronized ,剩下的都公平競(jìng)爭(zhēng)
-
可重入鎖 1)記錄當(dāng)前是哪個(gè)綫程使用這個(gè)鎖 2)在加鎖是判定,申請(qǐng)當(dāng)時(shí)鎖的綫程是否就是鎖的持有者綫程 3)計(jì)數(shù)器,記錄加鎖次數(shù),從而確定何時(shí)真正釋放鎖
-
不可重入鎖
-
死鎖問(wèn)題:針對(duì)一把鎖連續(xù)兩次加鎖就可能出現(xiàn)死鎖,可以把鎖設(shè)置成“可重入鎖”
-
讀寫(xiě)鎖
-
synchronized并非是讀寫(xiě)鎖
-
把加鎖操作分爲(wèi)“讀加鎖”和”寫(xiě)加鎖“,提供了兩種加鎖api,解鎖的api相同。
-
如果,多個(gè)線程,同時(shí)讀這個(gè)變量,沒(méi)有線程安全問(wèn)題。但是,一個(gè)線程讀/一個(gè)線程寫(xiě)或者兩個(gè)線程都寫(xiě)就會(huì)產(chǎn)生問(wèn)題,
-
如果兩個(gè)線程,都是按照讀方式加鎖,此時(shí)不會(huì)產(chǎn)生鎖沖突。如果兩個(gè)線程,都是加寫(xiě)鎖,此時(shí)會(huì)產(chǎn)生鎖沖突。如果一個(gè)線程讀鎖,一個(gè)是寫(xiě)鎖,也會(huì)產(chǎn)生鎖沖突。
-
系統(tǒng)內(nèi)置鎖,可重入讀寫(xiě)鎖ReentrantReadWriteLock。內(nèi)部類(lèi)ReentrantReadwriteLock.ReadLock/ReentrantReadWriteLock.WriteLock。lock/unlock方法。
1.2 synchronized原理
-
樂(lè)觀悲觀自適應(yīng)
-
重量輕量,自適應(yīng)
-
自旋掛起等待,自適應(yīng)
-
非公平鎖
-
可重入鎖
-
不是讀寫(xiě)鎖
-
鎖升級(jí):剛開(kāi)始使用synchronized加鎖,首先鎖會(huì)處于“偏向鎖”狀態(tài)。遇到線程之間的鎖競(jìng)爭(zhēng),升級(jí)到“輕量級(jí)鎖“。進(jìn)一步的統(tǒng)計(jì)競(jìng)爭(zhēng)出現(xiàn)的頻次,達(dá)到一定程度之后,升級(jí)到“重量級(jí)鎖”。
-
synchronized加鎖的時(shí)候,會(huì)經(jīng)歷無(wú)鎖=>偏向鎖=>輕量級(jí)鎖=>重量級(jí)鎖。出現(xiàn)競(jìng)爭(zhēng)/競(jìng)爭(zhēng)激烈。鎖升級(jí)對(duì)當(dāng)前jvm來(lái)説不可逆。
-
偏向鎖不是真鎖,只是做個(gè)標(biāo)記,比較輕量高效。
-
鎖消除。(編譯器優(yōu)化策略)
-
鎖粗化。(編譯器優(yōu)化策略)。鎖的粒度。synchronized{}裏代碼越多,粒度越粗。把多個(gè)”細(xì)粒度“的鎖合并成”粗粒度“的鎖。
1.3 CAS
-
compare and swap
-
比較內(nèi)存和cpu寄存器中的內(nèi)容.如果發(fā)現(xiàn)相同,就進(jìn)行交換(交換的是內(nèi)存和另一個(gè)寄存器的內(nèi)容)
-
比較內(nèi)存和寄存器1中的值,是否相等如果不相等,就無(wú)事發(fā)生。如果相等,就交換內(nèi)存和寄存器2的值
-
此處一般只是關(guān)心,內(nèi)存交換后的內(nèi)容。不關(guān)心寄存器2交換后的內(nèi)容。相當(dāng)於”賦值“
-
一個(gè)cpu指令就能完成。可以寫(xiě)”無(wú)鎖化編程“。
-
使用場(chǎng)景:
-
基於CAS實(shí)現(xiàn)”原子類(lèi)“。對(duì)int/long等類(lèi)型進(jìn)行封裝,從而可以原子地完成++等操作。標(biāo)準(zhǔn)庫(kù)裏也有。
package thread; ? import java.util.concurrent.atomic.AtomicInteger; ? public class Demo34 {// private static int count = 0;private static AtomicInteger count = new AtomicInteger(0); ?public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {count.getAndIncrement(); ?// count++ // ? ? ? ? ? ? ? count.incrementAndGet(); // ++count // ? ? ? ? ? ? ? count.getAndDecrement(); // count-- // ? ? ? ? ? ? ? count.decrementAndGet(); // --count // ? ? ? ? ? ? ? count.getAndAdd(10); ? ? ? // count+= 10}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {// count++;count.getAndIncrement();}});t1.start();t2.start();t1.join();t2.join(); ?// 通過(guò) count.get() 拿到原子類(lèi)內(nèi)部持有的真實(shí)數(shù)據(jù).System.out.println("count = " + count.get());} }
-