volatile的概念:
volatile與synchronized關(guān)鍵字是多線程并發(fā)編程中非常重要的知識點夕凝,通常被用于修飾變量晰韵。相比于synchroinized來說蔽介,volatile要輕量很多伐蒋,執(zhí)行的成本會更低灾票。原因是volatile不會引起線程上下文的切換和調(diào)度咽瓷,但是它與synchronized的意義其實是有區(qū)別的苟径。synchronized關(guān)鍵字主要體現(xiàn)的是互斥性贡避,而volatile體現(xiàn)的便是可見性战转、原子性搜立。從根本上來說,volatile用于多線程之間內(nèi)存的共享槐秧。
volatile使用意義:
Java內(nèi)存模型:
從下面圖中可以看出啄踊,java的內(nèi)存模型定義了主內(nèi)存和本地內(nèi)存,這是一種抽象的概念刁标。主內(nèi)存是所有線程可以共享的區(qū)域颠通,本地內(nèi)存為線程私有化。為了提高性能膀懈,線程通常不直接從主內(nèi)存中讀出和寫入內(nèi)容顿锰,而是通過本地內(nèi)存,并通過一定的刷新機制進行內(nèi)容同步启搂。本文主要介紹volatile相關(guān)知識硼控,關(guān)于java內(nèi)存模型內(nèi)容在后面專題分析。以下分別為不使用volatile和使用volatile關(guān)鍵字的區(qū)別:
volatile意義:
上圖看出胳赌,當線程A與線程B訪問同一個變量a時牢撼,若在線程A中將a的值從0修改為1,線程B中讀取變量a的值疑苫,依然是0熏版。而使用volatile關(guān)鍵字之后情況就不一樣,線程B讀取到a的值為1捍掺。原因在與撼短,沒有使用volatile關(guān)鍵字修飾變量時,線程A的修改只是在本地內(nèi)存A中挺勿,不會同步到主內(nèi)存阔加,線程B也只是從本地內(nèi)存B中讀取,因此無法實現(xiàn)修改同步满钟。使用volatile關(guān)鍵字之后胜榔,在線程A中修改了a的值,會將修改從本地內(nèi)存A寫入到主內(nèi)存中湃番,而當線程B讀取a的值時夭织,會直接從主內(nèi)存中讀取,并刷新本地內(nèi)存B吠撮。因此尊惰,線程A與線程B便能夠?qū)崿F(xiàn)內(nèi)存之間的共享了,實現(xiàn)內(nèi)存的可見性泥兰。
volatile實現(xiàn)原理:
被修飾變量值修改時處理器會將緩存行數(shù)據(jù)寫入到主內(nèi)存中
如果變量被聲明為volatile弄屡,當進行寫操作時,JVM會向處理器發(fā)送一條Lock前綴的指令鞋诗,然后將變量在緩存中所修改的值寫入到系統(tǒng)內(nèi)存中膀捷。
緩存一致性協(xié)議
如果volatile僅僅只有將緩存數(shù)據(jù)寫入到系統(tǒng)主存的能力,并不能實現(xiàn)線程之間的共享削彬。當有多個處理器存在的情況下全庸,為了保證各個處理器緩存內(nèi)容的一致性,處理器會實現(xiàn)緩存一致性協(xié)議融痛。每個處理器通過嗅探在總線上傳播的數(shù)據(jù)壶笼,檢查自己緩存的值是不是過期,當處理器發(fā)現(xiàn)自己緩存中所對應變量的內(nèi)存地址被修改時雁刷,就會將當前緩存行標志成無效狀態(tài)覆劈,當處理器需要讀取或是修改數(shù)據(jù)時,會直接從主內(nèi)存中加載數(shù)據(jù)到緩存中沛励,保證數(shù)據(jù)的一致性责语。
結(jié)束語
本篇只是概括性介紹volatile的一些基礎知識,對于原理的分析比較簡單易懂侯勉。如果要深入了解可以讀以下《java并發(fā)編程的藝術(shù)》一書鹦筹,書中有比較詳細的知識,或是參考這篇文章 正確使用 Volatile 變量