synchronized & volatile

synchronized & volatile

[toc]

實(shí)現(xiàn)多線程的兩種方式:①、繼承 Thread 類;②、實(shí)現(xiàn) Runnable 接口(推薦使用)。

非線程安全多個線程同一個對象中的同一個實(shí)例變量進(jìn)行操作時會出現(xiàn)值被更改、值不同步的情況,進(jìn)而影響程序的執(zhí)行流程。

守護(hù)線程:是為其他線程的運(yùn)行提供便利服務(wù)的,最典型的應(yīng)用就是 GC(垃圾回收線程)。

synchronized 關(guān)鍵字

synchronized 取得的鎖都是對象鎖,擁有鎖重入的功能。

鎖重入:當(dāng)一個線程得到一個對象鎖后,再次請求此對象鎖時,可以再次得到該對象的鎖的。

可重入鎖:比如:有一條線程獲得了某個對象的鎖,此時這個對象鎖還沒有被釋放,當(dāng)其想再次獲取這個對象的鎖時,還是可以獲取的。但如果不可鎖重入的話,就會出現(xiàn)死鎖。

synchronized 方法:對當(dāng)前對象進(jìn)行加鎖;
synchronized 代碼塊:對某一個對象進(jìn)行加鎖,默認(rèn)(this);

synchronized 同步代碼塊

  1. 同步代碼塊比同步方法范圍小。
  2. 同步代碼塊可以指定對象鎖。

synchronized(非 this 對象 X)

  1. synchronized(非 this 對象 X) 代碼塊中的程序,與同步方法是異步的,不會與其他鎖 this 同步方法爭搶 this 鎖,所以大大提高運(yùn)行效率。
  2. 解決"臟讀"問題。

靜態(tài)同步 synchronized 方法與 synchronized(Class) 代碼塊

  1. 非靜態(tài)同步 synchronized 方法是給對象加鎖;靜態(tài)同步 synchronized 方法是給 Class 加鎖的,對類的所有實(shí)例對象起作用。
  2. synchronized(class) 代碼塊與靜態(tài)同步 synchronized 方法作用一樣。

volatile 關(guān)鍵字

主要作用:使變量在多個線程之間可見

private boolean isRunning = true; 存在于公共堆棧線程的私有堆棧中。

volatile 的作用:強(qiáng)制從公共堆棧中取得變量的值,而不是從線程私有堆棧中取得

volatile 最致命的缺點(diǎn)不支持原子性。

Q:volatile & synchronized 的區(qū)別?

  1. volatile 只能修飾變量,而 synchronized 可以修飾方法、代碼塊
  2. volatile 性能比 synchronized ,但是使用幾率不大。
  3. 多線程訪問 volatile 不會發(fā)生阻塞,而 synchronized 會出現(xiàn)阻塞
  4. volatile 能保證數(shù)據(jù)的可見性,但不能保證原子性,而 synchronized 可以保證原子性、間接保證可見性(將私有內(nèi)存和公共內(nèi)存中的數(shù)據(jù)做同步
  5. volatile 解決的是變量在多個線程之間的可見性,而 synchronized 解決的是多個線程之間訪問資源的同步性

volatile 的非原子性

如果修改實(shí)例變量中的數(shù)據(jù),會出現(xiàn)非線程安全的問題。
,比如:i++,也就是 i = i + 1 并不是一個原子操作,也就是非線程安全的。i++ 的操作步驟分解如下:

  1. 從內(nèi)存中取出 i 值
  2. 計算 i 的值(此時,如果一個線程修改 i 的值,就出現(xiàn)臟數(shù)據(jù))
  3. 將 i 的值寫到內(nèi)存中

Q:為什么使用 volatile 會出現(xiàn)非線程安全的問題?

A:變量在內(nèi)存中工作的過程:

  1. read & load 階段:從主存復(fù)制變量到當(dāng)前線程工作內(nèi)存
  2. use & assign 階段:執(zhí)行代碼,改變共享變量值
  3. store & write 階段:用工作內(nèi)存數(shù)據(jù)刷新主存對應(yīng)變量的值

如果在 read & load 階段之后,變量發(fā)生修改,就會出現(xiàn)私有內(nèi)存公共內(nèi)存中的變量不同步,從而出現(xiàn)非線程安全問題。

volatile 總結(jié): 對于用 volatile 修飾的變量,JVM 虛擬機(jī)只是保證從主內(nèi)存加載到線程工作內(nèi)存的值是最新的。也就是說,volatile 關(guān)鍵字解決的是變量讀時的可見性問題,但無法保證原子性,對于多個線程訪問同一個實(shí)例變量還是需要加鎖同步。

synchronized 代碼塊有 volatile 同步的功能

synchronized 可以使多個線程訪問同一個資源具有同步性,而且它還具有將線程工作內(nèi)存中的私有變量公共變量同步的功能。

總結(jié):synchronized 不僅可以解決一個線程看到對象處于不一致的狀態(tài),還可以保證進(jìn)入同步方法或者同步代碼塊的每個線程,都看到由一個鎖保護(hù)之前所有的修改效果

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容