日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

java volidate线程安全_03.(多线程与并发)面试题-02--Volidate的原理和指令重排序

發布時間:2023/12/10 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java volidate线程安全_03.(多线程与并发)面试题-02--Volidate的原理和指令重排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線程棧(線程的工作內存)保存了線程運行時候變量值信息。當線程訪問某一個對象時候值的時候,首先通過對象的引用找到對應在堆內存的變量的值,然后把堆內存變量的具體值load到線程本地內存中,建立一個變量副本,之后線程就不再和對象在堆內存變量值有任何關系,而是直接修改副本變量的值,

在修改完之后的某一個時刻(線程退出之前),自動把線程變量本的值回寫到對象在堆中變量。這樣在堆中的對象的值就產生變化了。下面一幅圖副描述這寫交互

read and load 從主存復制變量到當前工作內存 use 代碼中使用值

assign ?改變共享變量值? store and write 用工作內存數據刷新主存相關內容

其中use and assign 可以多次出現

但是這一些操作并不是原子性,也就是 在read load之后,如果主內存count變量發生修改之后,線程工作內存中的值由于已經加載,不會產生對應的變化,所以計算出來的結果會和預期不一樣

總結:關鍵字上使用voildate之后,每一次use之前一定要read和load,這樣就保證了可見性,其他線程

指令重排序

總結:jvm會對指令執行的順序進行優化,這樣是為了提高執行的效率。但是在單線程的情況下指令的執行先后沒有關系,但是在多線程的情況下這些指令的執行順序就是對其他線程產生很大的影響。

很多介紹JVM并發的書或文章都會談到JVM為了優化性能,采用了指令重排序,但是對于什么是指令重排序,為什么重排序會優化性能卻很少有提及,其實道理很簡單,假設有這么兩個共享變量a和b:

private int a;

private int b;

在線程A中有兩條語句對這兩個共享變量進行賦值操作:

a = 1;

b = 2;

假設當線程A對a進行復制操作的時候發現這個變量在主內存已經被其它的線程加了訪問鎖,那么此時線程A怎么辦?等待釋放鎖?不,等待太浪費時間了,它會去嘗試進行b的賦值操作,b這時候沒被人占用,因此就會先為b賦值,再去為a賦值,那么執行的順序就變成了:

b = 2;

a = 1;

對于在同一個線程內,這樣的改變是不會對邏輯產生影響的,但是在多線程的情況下指令重排序會帶來問題,看下面這個情景:

在線程A中:

context = loadContext();

inited = true;

在線程B中:

while(!inited ){

sleep

}

doSomethingwithconfig(context);

假設A中發生了重排序:

inited = true;

context = loadContext();

那么B中很可能就會拿到一個尚未初始化或尚未初始化完成的context,從而引發程序錯誤。

想到有一條古老的原則很適合用在這個地方,那就是先要保證程序的正確然后再去優化性能。此處由于重排序產生的錯誤顯然要比重排序帶來的性能優化要重要的多。要解決重排序問題還是通過volatile關鍵字,volatile關鍵字能確保變量在線程中的操作不會被重排序而是按照代碼中規定的順序進行訪問,同時使用synchronized 關鍵字,里面也不會進行指令重排序。

總結

以上是生活随笔為你收集整理的java volidate线程安全_03.(多线程与并发)面试题-02--Volidate的原理和指令重排序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。