From:Java并發(fā)編程的藝術(shù)
- 目錄
BiBi - 并發(fā)編程 -0- 開(kāi)篇
BiBi - 并發(fā)編程 -1- 挑戰(zhàn)
BiBi - 并發(fā)編程 -2- volatile
BiBi - 并發(fā)編程 -3- 鎖
BiBi - 并發(fā)編程 -4- 原子操作
BiBi - 并發(fā)編程 -5- Java內(nèi)存模型
BiBi - 并發(fā)編程 -6- final關(guān)鍵字
BiBi - 并發(fā)編程 -7- DCL
BiBi - 并發(fā)編程 -8- 線程
BiBi - 并發(fā)編程 -9- ReentrantLock
BiBi - 并發(fā)編程 -10- 隊(duì)列同步器
BiBi - 并發(fā)編程 -11- 并發(fā)容器
BiBi - 并發(fā)編程 -12- Fork/Join框架
BiBi - 并發(fā)編程 -13- 并發(fā)工具類
BiBi - 并發(fā)編程 -14- 線程池
BiBi - 并發(fā)編程 -15- Executor框架
線程通信的兩種機(jī)制:共享內(nèi)存【隱式】和消息傳遞【顯示】,Java的并發(fā)采用共享內(nèi)存模型潮太,線程A向線程B發(fā)送消息舷胜,這個(gè)通信過(guò)程必須經(jīng)過(guò)主存析既。
指令重排序
編譯器和處理器為了優(yōu)化程序性能而對(duì)指令序列進(jìn)行重新排序惊橱,但不會(huì)對(duì)存在數(shù)據(jù)依賴關(guān)系的操作做重排序尤仍。
1)編譯器重排序
2)處理器重排序
包括:指令級(jí)并行的重排序【將多條指令重疊執(zhí)行】和內(nèi)存級(jí)重排序二汛。
對(duì)于處理器重排序遍烦,在Java編譯器生成指令序列時(shí)俭嘁,通過(guò)插入特定類型的內(nèi)存屏障【Memory Barriers / Memory Fence】指令來(lái)禁止重排序,從而保證內(nèi)存的可見(jiàn)性》恚現(xiàn)代的處理器都采用寫(xiě)緩沖區(qū)向內(nèi)存寫(xiě)入數(shù)據(jù)供填。
StoreLoad Barriers
StoreLoad Barriers屏障是一個(gè)【全能型】屏障,并且大部分處理器都支持罢猪,它會(huì)把寫(xiě)緩沖區(qū)中的數(shù)據(jù)全部刷新到內(nèi)存中近她。開(kāi)銷很高。
happens-before
使用happens-before來(lái)闡述操作之間的內(nèi)存可見(jiàn)性膳帕。
happens-before規(guī)則:
1)一個(gè)鎖的解鎖粘捎,先于隨后對(duì)這個(gè)鎖的加鎖
2)volatile變量的寫(xiě),先于任意后續(xù)對(duì)這個(gè)變量的的讀【volatile的本質(zhì)】
3)傳遞性:A先于B危彩,B先于C攒磨,則A先于C
happens-before提示:
具有happens-before關(guān)系,并不意味著前一個(gè)操作必須要在后一個(gè)操作之前執(zhí)行汤徽,僅僅要求前一個(gè)操作執(zhí)行的結(jié)果對(duì)后一個(gè)操作可見(jiàn)娩缰,并且前一個(gè)操作按順序排在第二個(gè)操作之前。
如果A線程的寫(xiě)操作a與B線程的讀操作b之間存在happens-before關(guān)系谒府,盡管a操作和b操作在不同的線程中執(zhí)行拼坎,但JMM保證a操作對(duì)b操作可見(jiàn)浮毯。
控制依賴重排序
if ( flag ) { // 1
int i = age + 10; // 2
}
操作1和操作2存在控制依賴關(guān)系,他們重排序后演痒,處理器可以提前讀取并計(jì)算age + 10
亲轨,然后把計(jì)算結(jié)果臨時(shí)保存到一個(gè)重排序緩沖的硬件緩存中。當(dāng)操作1的條件判斷為真時(shí)鸟顺,再把計(jì)算結(jié)果寫(xiě)入到變量i中惦蚊。
順序一致性
順序一致性模型簡(jiǎn)介:
1)順序一致性模型保證單線程內(nèi)的操作會(huì)按程序的順序執(zhí)行,而JMM不保證單線程內(nèi)的操作會(huì)按照程序的順序執(zhí)行【會(huì)重排序】讯嫂。
2)順序一致性模型保證所有線程只能看到一致的操作執(zhí)行順序蹦锋,而JMM不保證。
3)JMM不保證對(duì)64位的long型和double型變量的寫(xiě)操作具有原子性【JDK1.5之后讀具有原子性】欧芽,而順序一致性模型保證對(duì)所有的內(nèi)存讀/寫(xiě)操作都具有原子性莉掂。
第3)點(diǎn)與處理器的總線機(jī)制有關(guān)∏樱總線同步憎妙,在一個(gè)處理器執(zhí)行總線事物期間,總線會(huì)禁止其他的處理器和I/O設(shè)備的讀寫(xiě)操作曲楚。即總線工作機(jī)制:把所有處理器對(duì)內(nèi)存的訪問(wèn)以串行化的方式來(lái)執(zhí)行厘唾,在任意時(shí)間點(diǎn),最多只能有一個(gè)處理器可以訪問(wèn)內(nèi)存龙誊。確保單個(gè)總線事物之中的讀寫(xiě)操作具有原子性抚垃。
在32位處理器上,JVM可能把一個(gè)64位long/double型變量的寫(xiě)操作拆分成兩個(gè)32位的寫(xiě)操作來(lái)執(zhí)行趟大,這兩個(gè)32位的寫(xiě)操作可能會(huì)被分配到不同的總線事物中執(zhí)行鹤树,因此不具有原子性⊙沸啵【volatile類型的long/double讀寫(xiě)都具有原子性】
在單線程中重排序不會(huì)改變執(zhí)行結(jié)果罕伯,但在多線程中會(huì)影響執(zhí)行結(jié)果。
臨界區(qū)【鎖保護(hù)區(qū)】?jī)?nèi)的代碼可以重排序叽讳。