1.進(jìn)程間的通訊方式
1.1 共享內(nèi)存
1.2 消息隊列
1.3 管道
1.4 信號量(相當(dāng)于鎖機(jī)制)
2. 線程間通訊方式
2.1 鎖機(jī)制(Synchronized,Lock等)
2.2 線程同步(等待喚醒機(jī)制)
3. 并發(fā)編程的三大問題
3.1 可見性:當(dāng)一個線程修改了一個變量,另一個線程立馬可見,在java中采用兩種方式鎖,volatile修飾變量
volatile是如何實現(xiàn)可見性:volatile關(guān)鍵字產(chǎn)生的匯編指令前面有l(wèi)oc指令,該指令的作用就是將當(dāng)前處理器緩存行中的數(shù)據(jù)寫回系統(tǒng)內(nèi)存,Mesi協(xié)議:寫回內(nèi)存的操作回事其他CPU里面緩存了該內(nèi)存地址的數(shù)據(jù)無效。
3.2 順序性:代碼執(zhí)行的順序沒有按照預(yù)想的順序進(jìn)行,造成有序性的問題就是指令重排,分為編譯器的指令重排和處理器的指令重排,java編譯器通過插入內(nèi)存屏障來保證可見性,JVM提供四種標(biāo)準(zhǔn)的內(nèi)存屏障。
as-if-serial內(nèi)存模型
單線程程序執(zhí)行順序,不管怎么重排,程序的執(zhí)行結(jié)果不能被改變。必須遵守as-if-serial規(guī)則。
JMM happens-before原則

3.3 原子性:表示不可中斷的一個或一系列操作,volatile關(guān)鍵字無法保證原子性,原子性的保證需要通過加鎖或者JUC下提供的Atomic類
實現(xiàn)原理:synchronized底層匯編指令除了Lock之外還有一個是cmpxchg即為CAS是實現(xiàn),CAS具體實現(xiàn),總線鎖定LOCK或者緩存鎖定,在加鎖的時候首先對對象頭中的信息進(jìn)行CAS替換,然后對數(shù)據(jù)進(jìn)行操作,最后在釋放鎖的時候,將緩存中的值刷新回主內(nèi)存。
4. java中的鎖
自旋鎖: 線程通過循環(huán)的方式去嘗試獲取鎖直到成功
樂觀鎖: 當(dāng)線程需要修改數(shù)據(jù)的時候不需要加鎖,在修改數(shù)據(jù)時如果發(fā)現(xiàn)數(shù)據(jù)和之前獲取的不一致,則讀最新數(shù)據(jù),修改后重試修改
悲觀鎖: 加鎖
獨占鎖:只能有一個線程去獲取鎖
共享鎖:給資源加上讀鎖之后不能修改只能讀。
可重入鎖,不可重入鎖:線程拿到一把鎖之后,可以自由進(jìn)入同一把鎖同步的其他代碼塊
公平和非公平鎖
4.1 synchronized
- 可以用于實例方法,鎖的對象是this
- 用于static修飾的方法上鎖對象是class對象
- 鎖作用域自定義鎖對象
特殊優(yōu)化:鎖消除,鎖粗化
4. sychronized鎖升級

過程:無鎖->偏向鎖(JDK6以后默認(rèn)開啟偏向鎖的優(yōu)化,可以通過JVM參數(shù)控制是否開啟偏向鎖)->輕量級鎖->重量級鎖
當(dāng)線程需要進(jìn)入同步代碼塊的時候,先去檢查MARK word中的信息,如果是偏向鎖且持有的線程ID是當(dāng)前線程ID則進(jìn)入通過代碼塊,如果不是則嘗試使用CAS進(jìn)行替換,如果替換成功則進(jìn)入通過代碼塊,否則持有當(dāng)前偏向鎖的線程到安全點暫定然后將當(dāng)前Markword中的信息復(fù)制到自己的棧記錄中,搶占線程也復(fù)制,然后使用CAS將markword執(zhí)行執(zhí)行當(dāng)前線程棧記錄,繼續(xù)進(jìn)行執(zhí)行,否則進(jìn)行自選CAS嘗試替換,當(dāng)自選到一定地步然后會膨脹為重量級鎖monitor對象


suspend/resume不會釋放資源
wait/notify會釋資源,拋出異常
park/unpark不會釋放資源,可以提前喚醒,不拋出異常