Java關(guān)鍵字volatile和synchronized作用和區(qū)別
volatile是變量修飾符,而synchronized則是作用于一段代碼或方法;如下三句get代碼:
int i1; int geti1() {return i1;} volatile int i2; int geti2() {return i2;} int i3; synchronized int geti3() {return i3;}
geti1() 得到存儲(chǔ)在當(dāng)前線程中i1的數(shù)值。多個(gè)線程有多個(gè)i1變量拷貝,而且這些i1之間可以相互不同。換句話說,另一個(gè)線程可能已經(jīng)改變了它線程內(nèi)的i1值,而這個(gè)值可以和當(dāng)前線程中的i1值不相同。 在Java內(nèi)存模型中,有main memory(主內(nèi)存區(qū)域),這里存放了變量目前的“準(zhǔn)確值”,每個(gè)線程也有自己的memory(例如寄存器)。為了性能,一個(gè)線程會(huì)在自己的memory中保存要訪問的變量的副本。這樣就會(huì)出現(xiàn)同一個(gè)變量在某個(gè)瞬間,在一個(gè)線程的memory中的值可能與另外一個(gè)線程memory的值,或者main memory的值不一致的情況。因此實(shí)際上存在一種可能:main memory的值i1值是1,線程1里的i1是2,線程2里的i1值是3,這在線程1和線程2都改變了他們各自的i1值,而且這個(gè)改變還沒來得及傳給main memory 或其他線程時(shí)就會(huì)發(fā)生。
geti2() 得到的是main memory的i2數(shù)值。一個(gè)變量聲明為volatile,就意味著這個(gè)變量是隨時(shí)會(huì)被其他線程修改的,因此不能將它c(diǎn)ache在線程memory中。換句話說,一個(gè)變量經(jīng)過volatile修飾后在所有線程中必須是同步的,任何線程中改變了它的值,所有其他線程立即獲得了相同的值。所以,volatile修飾的變量存取時(shí)比一般變量消耗的資源要多一點(diǎn),因?yàn)榫€程有它自己的變量拷貝更為高效。
geti3()方法被synchronized修飾,用synchronized來修飾一個(gè)方法或者一個(gè)貸款的時(shí)候,能夠保證在同一時(shí)刻最多只有一個(gè)線程執(zhí)行該段代碼。既然volatile關(guān)鍵字已經(jīng)實(shí)現(xiàn)了線程間數(shù)據(jù)同步,又要synchronized干嘛呢?當(dāng)兩個(gè)并發(fā)線程訪問同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步貸款時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊才能執(zhí)行該代碼塊。然而,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),另一個(gè)線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí)候,其他線程對(duì)object中所有其他synchronized(this)同步代碼塊的訪問將被阻塞。當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),它就獲得了這個(gè)object的對(duì)象鎖,結(jié)果,其他線程對(duì)該對(duì)象所有同步代碼部分的訪問都被暫時(shí)阻塞。
總結(jié)一下區(qū)別:
一,volatile是變量修飾符,而synchronized則作用于一段代碼或者方法。
二,volatile只是在線程內(nèi)存和main memory(主內(nèi)存)間同步某個(gè)變量的值;而synchronized通過鎖定和解鎖某個(gè)監(jiān)視器同步所有變量的值。顯然synchronized要比volatile消耗更多資源。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 深入理解java中的synchronized關(guān)鍵字
- 詳解Java中synchronized關(guān)鍵字的死鎖和內(nèi)存占用問題
- Java中synchronized關(guān)鍵字修飾方法同步的用法詳解
- java多線程編程之使用Synchronized關(guān)鍵字同步類方法
- JAVA面試題 簡(jiǎn)談你對(duì)synchronized關(guān)鍵字的理解
- Java中使用synchronized關(guān)鍵字實(shí)現(xiàn)簡(jiǎn)單同步操作示例
- 舉例講解Java中synchronized關(guān)鍵字的用法
- 實(shí)例解析Java中的synchronized關(guān)鍵字與線程安全問題
- Java關(guān)鍵字synchronized基本使用詳解
相關(guān)文章
SpringBoot?@GroupSequenceProvider注解實(shí)現(xiàn)bean多屬性聯(lián)合校驗(yàn)的示例代碼
這篇文章主要介紹了SpringBoot?@GroupSequenceProvider注解實(shí)現(xiàn)bean多屬性聯(lián)合校驗(yàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08詳解SpringBoot?統(tǒng)一后端返回格式的方法
今天我們來聊一聊在基于SpringBoot前后端分離開發(fā)模式下,如何友好的返回統(tǒng)一的標(biāo)準(zhǔn)格式以及如何優(yōu)雅的處理全局異常,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2022-05-05Java文件讀寫IO/NIO及性能比較詳細(xì)代碼及總結(jié)
這篇文章主要介紹了Java文件讀寫IO/NIO及性能比較詳細(xì)代碼及總結(jié),具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12基于spring?data?jpa?@query返回map的踩坑記錄
這篇文章主要介紹了基于spring?data?jpa?@query返回map的踩坑記錄,具有很好的參考價(jià)值,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11SpringBoot項(xiàng)目中訪問HTML頁面的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot項(xiàng)目中訪問HTML頁面的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08SpringCloud Alibaba Seata (收藏版)
Seata是一款開源的分布式事務(wù)解決方案,致力于在微服務(wù)架構(gòu)在提供高性能和簡(jiǎn)單一樣的分布式事務(wù)服務(wù)。這篇文章主要介紹了SpringCloud Alibaba Seata 的相關(guān)知識(shí),需要的朋友可以參考下2020-10-10微信小程序+后端(java)實(shí)現(xiàn)開發(fā)
這篇文章主要介紹了微信小程序+后端(java)實(shí)現(xiàn)開發(fā),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04