一、volatile
- 1.volatile的底層原理是內(nèi)存屏障,Memory Barrier, Memory Fence
- 2.對(duì)volatile變量的寫指令(賦值操作)后會(huì)加入寫屏障
- 3.對(duì)volatile變量的讀指令(取變量值)前會(huì)加入讀屏障
- 4.寫屏障的作用會(huì)將寫屏障之前的賦值改動(dòng)操作,對(duì)共享變量的改動(dòng)都同步到主內(nèi)存中
- 5.讀屏障的作用會(huì)將讀屏障之后的對(duì)共享變量的讀取,加載的是主存中最新的數(shù)據(jù)
- 6.寫屏障的作用會(huì)確保指令重排序時(shí),不會(huì)將寫屏障之前的代碼排在寫屏障之后
- 7.讀屏障的作用會(huì)確保指令重排序時(shí),不會(huì)將讀屏障之后的代碼排在讀屏障之前
- 8.不能解決指令交錯(cuò),寫屏障僅僅是保證之后的讀能夠讀到最新的結(jié)果,不能保證另個(gè)線程b在線程a寫之前讀,然后在線程a寫之后,線程b再寫
- 9.有序性的保證只保證了本線程內(nèi)相關(guān)代碼不被重新排序
- 10.jdk1.5之后才能生效
二、保證可見性
- 1.寫屏障(sfence)保證在該屏障之前的,對(duì)共享變量的改動(dòng),都同步到主存之中
- 2.volatile a變量,當(dāng)a變量被賦值后,a=1后會(huì)加入一個(gè)寫屏障,會(huì)將a=1賦值操作之前的對(duì)共享變量的改動(dòng)都同步到主存中
- 3.讀屏障(lfence)保證在該屏障之后,對(duì)共享變量的讀取,加載的是主存中最新數(shù)據(jù)
- 4.volatile a變量,當(dāng)if(a==2)時(shí),讀取a變量前會(huì)加一個(gè)讀屏障,在讀屏障之后對(duì)共享變量的讀取加載的都是主存中最新的數(shù)據(jù)
三、保證有序性
- 1.寫屏障會(huì)確保指令重排時(shí),不會(huì)將寫屏障之前的代碼排在寫屏障之后,例如int a = 2;boolean b = true; 假如b是被volatile關(guān)鍵字修飾,則給b賦值為true之后,會(huì)產(chǎn)生一個(gè)寫屏障,那么寫屏障之前的操作 a=2的賦值操作不會(huì)重排到寫屏障之后,也就是保證了a=2賦值操作在b=true的賦值操作之前
- 2.讀屏障會(huì)確保指令重排時(shí),不會(huì)將讀屏障之后的代碼排在讀屏障之前,例如if(b); int a = 2; 假如b是被volatile關(guān)鍵字修飾,則讀取b變量時(shí),會(huì)給b變量讀操作前加一個(gè)讀屏障,在讀屏障之后的代碼a=2,不會(huì)重排在讀屏障之前,因此保證a=2操作在if(b)讀b變量之后
四、不能解決指令交錯(cuò)
- 1.線程a和線程b,修改volatile關(guān)鍵字修飾的變量i
- 2.線程a對(duì)變量i進(jìn)行自加1操作,線程b對(duì)變量i進(jìn)行自減1操作
- 3.開始線程a讀取變量i為0,線程b讀取變量i為0
- 4.線程a自加1成功,并將i=1寫回主存,線程b自減成功,并將i=-1寫回主存
- 5.此時(shí)主存中變量i的值為-1,正常來(lái)說(shuō)結(jié)果應(yīng)該是0
- 6.且在線程a、b各自的線程內(nèi),都能保證各自的指令有序,不能重排序
- 7.因此volatile關(guān)鍵字修飾的變量沒(méi)有解決指令交錯(cuò)帶來(lái)的線程安全問(wèn)題
- 8.線程a、線程b之間的指令會(huì)有一定的交錯(cuò),volatile不能保證原子性
- 9.synchronized可以保證可見性、有序性和原子性(共享變量要完全在synchronized代碼塊內(nèi),如果代碼塊外部還有變量的使用,則不能保證指令不重排)
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-462703.html
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-462703.html
到了這里,關(guān)于【多線程】volatile關(guān)鍵字的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!