- 判斷一個(gè)程序是不是存在數(shù)據(jù)競爭
如果一個(gè)程序中存在兩個(gè)有沖突但不存在happens-before
偏序關(guān)系的操作,則稱這個(gè)程序是存在數(shù)據(jù)競爭的询微。
【案例1】假設(shè)r1
和r2
是局部變量炫隶,A
和B
是共享變量洞辣,則
Thread 1 | Thread 2 |
---|---|
1: r2 = A;
|
3: r1 = B;
|
2: B = 1;
|
4: A = 2;
|
由于
- 操作1和操作4是存在沖突的,且不存在happens-before偏序關(guān)系码俩;
- 操作2和操作3是存在沖突的度帮,且不存在happens-before偏序關(guān)系;
所以這個(gè)程序是存在數(shù)據(jù)競爭的稿存。
- 定義了一個(gè)
happens-before
一致性內(nèi)存模型
對于被同步的共享變量笨篷,保證弱一致性,通過加內(nèi)存屏障(Memory Barrier)和緩存一致性協(xié)議實(shí)現(xiàn)瓣履,具體地講:
- 讀volatile變量或者進(jìn)入鎖率翅,都會保證進(jìn)入一致性;
- 寫volatile變量或者釋放鎖拂苹,都會保證釋放一致性安聘;
- 同步變量的操作不允許進(jìn)行指令重排序,保證了其順序性瓢棒;
結(jié)合Pentium和PowerPC處理器中廣泛使用的一種主流的緩存一致性協(xié)議--MESI來解釋下浴韭。
假設(shè)CPU1執(zhí)行線程A,CPU2執(zhí)行線程B脯宿;CPU1和CPU2都有高速緩存念颈;線程A和線程B共享volatile變量started,
- 當(dāng)CPU1從地址started=false讀取數(shù)據(jù)连霉,會廣播它的讀請求榴芳,如果沒有收到響應(yīng)嗡靡,即表明CPU1是最先開始讀取started的,然后將數(shù)據(jù)存入它的緩存并置為exclusive窟感;
- 當(dāng)CPU2也從地址started讀取數(shù)據(jù)時(shí)讨彼,會廣播它的讀請求:CPU1在收到該讀請求后,檢測到地址沖突柿祈,將緩存中的拷貝狀態(tài)置為為shared哈误,作為響應(yīng);CPU2收到CPU1的響應(yīng)后躏嚎,將數(shù)據(jù)存入它的緩存并置為shared蜜自;
- 當(dāng)CPU2寫started,即started=true時(shí)卢佣,將緩存中started狀態(tài)置為modified重荠,并廣播其寫請求;CPU1在收到請求后虚茶,將started的拷貝狀態(tài)置為Invalid戈鲁,作為響應(yīng);
- 當(dāng)CPU1再從started讀取數(shù)據(jù)時(shí)媳危,會廣播它的讀請求荞彼;CPU2收到請求后冈敛,將started=true的數(shù)據(jù)發(fā)送到CPU1和刷新到主內(nèi)存待笑,設(shè)置started拷貝的狀態(tài)為shared,作為響應(yīng)抓谴;CPU1收到CPU2的響應(yīng)后暮蹂,將數(shù)據(jù)存入它的緩存并置為shared;
對于沒有被同步的共享變量癌压,
- 只保證其正確性仰泻,即從單線程執(zhí)行的角度來說,程序的執(zhí)行結(jié)果和程序定義的結(jié)果是一致性的滩届;
- 不保證其順序性集侯,因?yàn)闆]有數(shù)據(jù)相關(guān)性的代碼是可以重排序的;
- 判斷一個(gè)程序是不是被正確地同步了
一個(gè)程序里的所有具有順序一致性的執(zhí)行都是無數(shù)據(jù)競爭的當(dāng)且僅當(dāng)這是一個(gè)被正確同步的程序帜消。
根據(jù)上述定義棠枉,顯然有:
- 如果一個(gè)程序被正確同步了,則就不需要考慮代碼重排因素對程序的影響了泡挺;
- 正確同步一個(gè)程序可以用來防止由于代碼重排導(dǎo)致的違反直覺的執(zhí)行結(jié)果辈讶,但并不保證一個(gè)程序的正確性;
- 如果一個(gè)程序被正確同步了娄猫,則程序員就可以以一種簡單的方式來考慮程序的執(zhí)行了贱除;
具體的案例請參考:
https://github.com/liyanghao/java-study/blob/master/src/concurrency/happens-before-examples.md
【參考資料】
- https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5
- 《聊聊高并發(fā)(三十三)Java內(nèi)存模型那些事(一)從一致性(Consistency)的角度理解Java內(nèi)存模型》http://blog.csdn.net/iter_zc/article/details/41943387
- 《深入理解Java內(nèi)存模型(三)——順序一致性》http://www.infoq.com/cn/articles/java-memory-model-3
- 《為什么程序員需要關(guān)心順序一致性(Sequential Consistency)而不是Cache一致性(Cache Coherence生闲?)》
http://www.infoq.com/cn/articles/java-memory-model-3