Java并發(fā)編程之關(guān)鍵字volatile知識(shí)總結(jié)
一、作用
被 volatile 修飾的變量
1.保證了不同線程對(duì)該變量操作的內(nèi)存可見性
2.禁止指令重排序
二、可見性
Java 內(nèi)存模型(Java Memory Model) 是 Java 虛擬機(jī)定義的一種規(guī)范,即每個(gè)線程都有自己的工作空間,線程對(duì)變量的操作都在線程的工作內(nèi)存中完成,再同步到主存中,這樣可能會(huì)導(dǎo)致不同的線程對(duì)共享變量的操作,在各自線程工作空間內(nèi)不一樣的問題。
而用 volatile 修飾的變量,線程對(duì)該變量的修改,會(huì)立刻刷新到主存,其它線程讀取該變量時(shí),會(huì)重新去主存讀取新值。
三、有序性
CPU 為了提供程序的運(yùn)行效率,會(huì)對(duì)代碼的執(zhí)行順序進(jìn)行重排,因此代碼中各個(gè)語句的先后執(zhí)行順序有可能會(huì)變化,但是它會(huì)保證程序最終執(zhí)行結(jié)果與代碼順序執(zhí)行結(jié)果一致。
指令重排序會(huì)考慮數(shù)據(jù)之間的依賴性,不會(huì)影響單個(gè)線程內(nèi)程序的執(zhí)行結(jié)果
c = 2 可能在 a = 1之前執(zhí)行
int a = 1; int c = 2;
volatile 修飾的變量具有有序性,即被 volatile 修飾的變量,在其前面的操作與在其后面的操作的執(zhí)行順序不能打亂。
int a= 1; volatile b = 2; int c = 2;
a = 1 一定在 c = 2 前面執(zhí)行,volatile 的作用好像在兩者之間插入了一個(gè)內(nèi)存屏障
對(duì)于 volatile 的有序性應(yīng)用,一般常用 double-check 的單例模式來說明
public class Singleton { private Singleton(){} private static volatile Singleton singleton; public static Singleton getSingleton(){ if (singleton == null){ synchronized(Singleton.class){ if (singleton == null){ singleton = new Singleton(); } } } return singleton } }
singleton = new Singleton(); 分為 3 步
1.new Singleton() 開辟堆內(nèi)存空間
2.初始化 singleton 對(duì)象
3.將 singleton 對(duì)象指向堆內(nèi)存地址
第 3 步可能在第 2 步之前執(zhí)行,那么其它線程可能得到為初始化完成的 singleton 對(duì)象,造成異常。
四、happens-before
- 程序順序規(guī)則: 一個(gè)線程中的每個(gè)操作,happens-before于該線程中的任意后續(xù)操作
- 監(jiān)視器鎖規(guī)則:對(duì)一個(gè)線程的解鎖,happens-before 于隨后對(duì)這個(gè)線程的加鎖
- volatile 變量規(guī)則: 對(duì)一個(gè) volatile 域的寫,happens-before 于后續(xù)對(duì)這個(gè) volatile 域的讀
- 傳遞性:如果 A happens-before B ,且 B happens-before C, 那么 A happens-before C
- start()規(guī)則: 如果線程A執(zhí)行操作ThreadB_start()(啟動(dòng)線程B) , 那么A線程的ThreadB_start()happens-before 于B中的任意操作
- join()原則: 如果A執(zhí)行ThreadB.join()并且成功返回,那么線程B中的任意操作happens-before于線程A從ThreadB.join()操作成功返回。
- interrupt()原則: 對(duì)線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程代碼檢測到中斷事件的發(fā)生,可以通過Thread.interrupted()方法檢測是否有中斷發(fā)生
- finalize()原則:一個(gè)對(duì)象的初始化完成先行發(fā)生于它的finalize()方法的開始
五、與 Synchronized 對(duì)比
1.volatile 只能作用于變量,synchronized 可以作用于變量,方法,代碼塊
2.volatile 不保證原子性,synchronized 可以保證
3.訪問 volatile 修飾的變量不會(huì)阻塞,synchronized 可能會(huì)
到此這篇關(guān)于Java并發(fā)編程之關(guān)鍵字volatile知識(shí)總結(jié)的文章就介紹到這了,更多相關(guān)Java關(guān)鍵字volatile內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot+dubbo啟動(dòng)項(xiàng)目時(shí)報(bào)錯(cuò) zookeeper not connect
這篇文章主要介紹了springboot+dubbo項(xiàng)目啟動(dòng)項(xiàng)目時(shí)報(bào)錯(cuò) zookeeper not connected的問題,本文給大家定位問題及解決方案,結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2023-06-06OutOfMemoryError內(nèi)存不足和StackOverflowError堆棧溢出示例詳解
這篇文章主要為大家介紹了OutOfMemoryError內(nèi)存不足和StackOverflowError堆棧溢出示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Spring cloud Eureka注冊(cè)中心搭建的方法
這篇文章主要介紹了Spring cloud Eureka注冊(cè)中心搭建的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04java學(xué)習(xí)筆記之eclipse+tomcat 配置
俗話說:工欲善其事必先利其器,既然要學(xué)習(xí)java,首先把java的開發(fā)環(huán)境搗鼓一下吧,這里我們來談?wù)別clipse+tomcat的配置方法。2014-11-11SpringBoot 實(shí)戰(zhàn) 之 優(yōu)雅終止服務(wù)的方法
本篇文章主要介紹了SpringBoot 實(shí)戰(zhàn) 之 優(yōu)雅終止服務(wù)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05java web實(shí)現(xiàn)分頁查詢實(shí)例方法
在本篇文章里我們給大家分享了java web實(shí)現(xiàn)分頁查詢的詳細(xì)方法知識(shí)點(diǎn),有需要的朋友們參考學(xué)習(xí)下。2018-10-10