欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java線程中synchronized和volatile關(guān)鍵字的區(qū)別詳解

 更新時(shí)間:2024年01月30日 09:44:40   作者:saint_motel  
這篇文章主要介紹了Java線程中synchronized和volatile關(guān)鍵字的區(qū)別詳解,synchronzied既能夠保障可見(jiàn)性,又能保證原子性,而volatile只能保證可見(jiàn)性,無(wú)法保證原子性,volatile不需要加鎖,比synchronized更輕量級(jí),不會(huì)阻塞線程,需要的朋友可以參考下

前言

提到synchronized和volatile這兩個(gè)有關(guān)線程的關(guān)鍵字,那我們先來(lái)說(shuō)一下Java的內(nèi)存模型(JMM)。

Java內(nèi)存模型(java Memory Model)描述了Java程序中各種變量(線程共享變量)的訪問(wèn)規(guī)則,以及在JVM中將變量存儲(chǔ)到內(nèi)存和從內(nèi)存中讀取出變量這樣的底層細(xì)節(jié)。

首先了解兩個(gè)概念:

  1. 可見(jiàn)性: 一個(gè)線程對(duì)共享變量值的修改,能夠及時(shí)地被其他線程看到。
  2. 共享變量: 如果一個(gè)變量在多個(gè)線程的工作內(nèi)存中都存在副本,那么這個(gè)變量就是這幾個(gè)線程的共享變量。

共享變量可見(jiàn)性實(shí)現(xiàn)的原理

線程1對(duì)共享變量的修改要想被線程2及時(shí)看到,必須要經(jīng)過(guò)以下兩個(gè)步驟:

  1. 在工作內(nèi)存1中更新過(guò)的共享變量刷新到主內(nèi)存中;
  2. 將主內(nèi)存中最新的共享變量的值更新到在工作內(nèi)存2中

其中線程對(duì)共享變量的操作,遵循以下兩個(gè)規(guī)則:

  1. 線程對(duì)共享變量的所有操作都必須在自己的工作內(nèi)存中進(jìn)行,不能直接從主內(nèi)存中讀寫;
  2. 不同線程之間無(wú)法直接訪問(wèn)其他線程工作內(nèi)存的變量,線程間變量值的傳遞需要通過(guò)主內(nèi)存來(lái)完成。

可見(jiàn)性 

要實(shí)現(xiàn)共享變量的可見(jiàn)性,必須保證兩點(diǎn):

  • 線程修改后的共享變量能夠及時(shí)從工作內(nèi)存刷新到主內(nèi)存中
  • 其他線程能夠及時(shí)把共享變量的最新值從主內(nèi)存更新到自己的工作內(nèi)存中

可見(jiàn)性的實(shí)現(xiàn)方式:

  • synchronized
  • volatile

synchronized實(shí)現(xiàn)可見(jiàn)性

  • 線程解鎖前,必須把共享變量的最新值刷新到主內(nèi)存中;
  • 線程加鎖時(shí),將清空工作內(nèi)存中共享變量的值,從而使用共享變量時(shí),需要從主內(nèi)尋中重新讀取最新的值(注意:加鎖和解鎖試一把鎖)

注意:線程解鎖前對(duì)共享變量的修改在下次加鎖時(shí)對(duì)其他線程可見(jiàn)

線程執(zhí)行互斥代碼的過(guò)程:

  • 獲得互斥鎖;
  • 清空工作內(nèi)存;
  • 從主內(nèi)存拷貝變量的最新副本到工作的內(nèi)存;
  • 執(zhí)行代碼;
  • 將更改后的共享變量的值刷新到主內(nèi)存;
  • 釋放互斥鎖.

重排序:

代碼書寫的順序與實(shí)際執(zhí)行的順序不同,指令重排序是編譯器或處理器為了提高程序性能而做的優(yōu)化

  •  編譯器優(yōu)化的重排序(編譯器優(yōu)化)
  • 指令級(jí)并行重排序(處理器優(yōu)化)
  • 內(nèi)存系統(tǒng)的重排序(處理器優(yōu)化)

volatile實(shí)現(xiàn)可見(jiàn)性

volatile通過(guò)加入內(nèi)存屏障和禁止重排序優(yōu)化來(lái)實(shí)現(xiàn)的

  • 對(duì)volatile變量執(zhí)行寫操作時(shí),會(huì)在寫操作后加入一條store屏障指令
  • 對(duì)volatile變量執(zhí)行讀操作時(shí),會(huì)在讀操作前加入一條load屏障指令

線程寫volatile變量的過(guò)程:

  1. 改變線程工作內(nèi)存中volatile變量副本的值
  2. 將改變后的副本的值從工作內(nèi)存刷新到主內(nèi)存 

線程讀volatile變量的過(guò)程:

  • 從主內(nèi)存中讀取volatile變量的最新值到線程的工作內(nèi)存中;
  • 從工作內(nèi)存中讀取volatile變量的副本; 

volatile不能保證volatile變量復(fù)合操作的原子性:

不是原子操作;

private int number = 0;
number ++ ;

加入synchronized,變?yōu)樵硬僮?/p>

synchronized(this){
  number++;
}

變?yōu)関olatile變量,無(wú)法保障原子性

private volatile int number = 0;

解決方案:

保證number自增操作的原子性:

  • 使用synchronized關(guān)鍵字
  • 使用ReentrantLock(java.util.concurrent.locks包下)
  • 使用AtomicInterger(java.util.concurrent.atomic包下)
    //Reentranlock
    public int increase(){
	lock.lock();
	try{
		number++;
	}finally{
		lock.unlock();
	}
	return number;
}

volatile適用場(chǎng)合

要在多線程中安全的使用volatile變量,必須同時(shí)滿足:

  • 對(duì)變量的寫入操作不依賴其當(dāng)前值;
    • 不滿足:number++、count=count *5等
    • 滿足:boolean變量、記錄溫度變化的變量等
  • 該變量沒(méi)有包含在具有其他變量的不變式中
    •  不滿足: low<up

總結(jié)

synchronized和volatile的區(qū)別

volatile不需要加鎖,比synchronized更輕量級(jí),不會(huì)阻塞線程;從內(nèi)存可見(jiàn)性角度,volatile讀相當(dāng)于加鎖,volatile寫相當(dāng)于解鎖;synchronzied既能夠保障可見(jiàn)性,又能保證原子性,而volatile只能保證可見(jiàn)性,無(wú)法保證原子性。

到此這篇關(guān)于Java線程中synchronized和volatile關(guān)鍵字的區(qū)別詳解的文章就介紹到這了,更多相關(guān)synchronized和volatile關(guān)鍵字內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Maven-POM文件及組成部分

    Maven-POM文件及組成部分

    POM是用于描述Maven項(xiàng)目的配置文件,它包含了項(xiàng)目構(gòu)建、依賴管理和其他相關(guān)配置的信息,這篇文章主要介紹了Maven-POM文件,需要的朋友可以參考下
    2023-06-06
  • java中使用url進(jìn)行編碼和解碼

    java中使用url進(jìn)行編碼和解碼

    這篇文章主要介紹了java中使用url進(jìn)行編碼和解碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 每日幾道java新手入門面試題,通往自由的道路

    每日幾道java新手入門面試題,通往自由的道路

    這篇文章主要為大家分享了最有價(jià)值的是幾道java面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對(duì)hashCode方法的設(shè)計(jì)、垃圾收集的堆和代進(jìn)行剖析,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java中Stream流去除List重復(fù)元素的方法

    Java中Stream流去除List重復(fù)元素的方法

    這篇文章主要為大家詳細(xì)介紹了Java中Stream流去除List重復(fù)元素的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 流式圖表拒絕增刪改查之框架搭建過(guò)程

    流式圖表拒絕增刪改查之框架搭建過(guò)程

    這篇文章主要為大家介紹了流式圖表拒絕增刪改查之框架搭建過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Java中內(nèi)部類的概念與分類詳解

    Java中內(nèi)部類的概念與分類詳解

    一個(gè)類的定義放在另一個(gè)類的內(nèi)部,這個(gè)類就叫做內(nèi)部類,下面這篇文章主要給大家介紹了關(guān)于Java中內(nèi)部類的概念與分類的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • Java mockito單元測(cè)試實(shí)現(xiàn)過(guò)程解析

    Java mockito單元測(cè)試實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了Java mockito單元測(cè)試實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 解決springboot項(xiàng)目打成jar包后運(yùn)行時(shí)碰到的小坑

    解決springboot項(xiàng)目打成jar包后運(yùn)行時(shí)碰到的小坑

    這篇文章主要介紹了解決springboot項(xiàng)目打成jar包后運(yùn)行時(shí)碰到的小坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java中HTTP GET方法調(diào)用帶有body的問(wèn)題解決

    Java中HTTP GET方法調(diào)用帶有body的問(wèn)題解決

    這篇文章主要為大家詳細(xì)介紹了Java如何解決HTTP GET方法調(diào)用帶有body的問(wèn)題,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下
    2024-02-02
  • SpringAop攔截參數(shù)帶注解的方法

    SpringAop攔截參數(shù)帶注解的方法

    這篇文章主要介紹了SpringAop攔截參數(shù)帶注解的方法,本文給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2024-12-12

最新評(píng)論