日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

java 挥发注解_Java的挥发性修饰符

發(fā)布時(shí)間:2023/12/3 java 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 挥发注解_Java的挥发性修饰符 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

java 揮發(fā)注解

不久前,我寫了一個(gè)Java servlet過(guò)濾器,該過(guò)濾器在其init函數(shù)中加載配置(基于web.xml的參數(shù))。 篩選器的配置緩存在私有字段中。 我在字段上設(shè)置了volatile修飾符。

后來(lái),當(dāng)我檢查Sonar公司以查看是否在代碼中發(fā)現(xiàn)任何警告或問(wèn)題時(shí),得知使用volatile違反了規(guī)定,我感到有些驚訝。 解釋為:




通常使用關(guān)鍵字“ volatile”來(lái)微調(diào)Java應(yīng)用程序,因此需要Java內(nèi)存模型的專業(yè)知識(shí)。 而且,它的作用范圍還有些未知。 因此,volatile關(guān)鍵字不應(yīng)用于維護(hù)目的和可移植性。

我同意volatile是許多Java程序員所不知道的。 對(duì)于一些甚至未知。 不僅因?yàn)樗鼜囊婚_(kāi)始就沒(méi)有使用太多,還因?yàn)樗亩x自Java 1.5起就發(fā)生了變化。

讓我稍微回顧一下Sonar的違規(guī)行為,并首先解釋volatile在Java 1.5及更高版本中的含義(直到撰寫本文時(shí)Java 1.8)。

什么是揮發(fā)物?

盡管volatile修飾符本身來(lái)自C,但在Java中它具有完全不同的含義。 這可能無(wú)助于加深對(duì)它的理解,使用谷歌搜索揮發(fā)物可能會(huì)導(dǎo)致不同的結(jié)果。 讓我們快速邁出第一步,看看volatile在C語(yǔ)言中的含義。

在C語(yǔ)言中,編譯器通常假定變量無(wú)法自行更改值。 盡管這是默認(rèn)行為,但有時(shí)變量可能表示可以更改的位置(例如硬件寄存器)。 使用易失性變量指示編譯器不要應(yīng)用這些優(yōu)化。

回到Java。 C中的volatile的含義在Java中將毫無(wú)用處。 JVM使用本機(jī)庫(kù)與操作系統(tǒng)和硬件進(jìn)行交互。 此外,將Java變量指向特定地址根本是不可能的,因此變量實(shí)際上不會(huì)自行更改值。

但是,JVM上變量的值可以由不同的線程更改。 默認(rèn)情況下,編譯器假定變量不會(huì)在其他線程中更改。 因此,它可以應(yīng)用優(yōu)化,例如對(duì)存儲(chǔ)器操作重新排序以及將變量緩存在CPU寄存器中。 使用易失性變量指示編譯器不要應(yīng)用這些優(yōu)化。 這樣可以保證讀取線程始終從內(nèi)存(或共享緩存)中讀取變量,而不從本地緩存中讀取變量。

原子性

此外,關(guān)于32位JVM volatile的更多信息將寫入到64位可變?cè)?#xff08;如long s和double s)。 要寫入變量,JVM會(huì)指示CPU將操作數(shù)寫入內(nèi)存中的某個(gè)位置。 使用32位指令集時(shí),如果變量的大小為64位怎么辦? 顯然,該變量必須用兩條指令(一次32位)寫入。

在多線程方案中,另一個(gè)線程可能會(huì)在寫入過(guò)程中讀取變量。 此時(shí),僅寫入變量的前半部分。 這種爭(zhēng)用條件可以通過(guò)可變的方式來(lái)防止,從而有效地使對(duì)32位體系結(jié)構(gòu)的64位變量進(jìn)行原子寫操作。

請(qǐng)注意,上面我談到的是寫而不是更新 。 使用volatile不會(huì)使更新原子化。 例如,當(dāng)i易失時(shí), ++i將從堆或L3緩存中讀取i的值到本地寄存器inc中,然后將該寄存器寫回到i的共享位置。 在讀寫之間, i可能會(huì)被另一個(gè)線程更改。 在讀寫指令周圍加一個(gè)鎖,使更新成為原子操作。 或更妙的是,使用concurrent.atomic包中原子變量類的非阻塞指令。

副作用

volatile變量在內(nèi)存可見(jiàn)性方面也有副作用。 當(dāng)線程讀取volatile變量時(shí),不僅對(duì)volatile變量的更改對(duì)其他線程可見(jiàn),而且導(dǎo)致更改的代碼的任何副作用也可見(jiàn)。 或更正式地說(shuō),易失性變量與該變量的后續(xù)讀取之間建立事前關(guān)聯(lián)。

即,從內(nèi)存可見(jiàn)性的角度來(lái)看,有效地寫入易失性變量就像退出同步塊并讀取易失性變量就像進(jìn)入變量一樣。

選擇易失性

回到我使用volatile一次初始化配置并將其緩存在私有字段中的情況。
到目前為止,我相信確保此字段對(duì)所有線程可見(jiàn)的最佳方法是使用volatile。 我本來(lái)可以使用AtomicReference 。 由于該字段僅被寫入一次(構(gòu)造之后,因此不可能是最終的),因此原子變量傳達(dá)了錯(cuò)誤的意圖。 我不想使更新原子化,我想使緩存對(duì)所有線程可見(jiàn)。 對(duì)于它的價(jià)值,原子類也使用volatile。

關(guān)于聲納法則的思考

既然我們已經(jīng)了解了volatile在Java中的含義,那么讓我們進(jìn)一步討論一下Sonar規(guī)則。

我認(rèn)為該規(guī)則是Sonar之類的工具配置中的缺陷之一。 如果需要跨線程共享(可變)狀態(tài),那么使用volatile可能是一件非常好的事情。 當(dāng)然,您必須將此保持在最低水平。 但是,此規(guī)則的結(jié)果是,不了解什么是揮發(fā)物的人會(huì)遵循建議不要使用揮發(fā)物。 如果他們有效地刪除修飾符,則會(huì)引入競(jìng)爭(zhēng)條件。

我確實(shí)認(rèn)為使用未知或危險(xiǎn)的語(yǔ)言功能時(shí)自動(dòng)升起紅色標(biāo)記是個(gè)好主意。 但是,當(dāng)有更好的替代方法來(lái)解決同一問(wèn)題時(shí),也許這只是一個(gè)好主意。 在這種情況下,volatile沒(méi)有其他選擇。

請(qǐng)注意,這絕不是對(duì)Sonar的指責(zé)。 但是我確實(shí)認(rèn)為人們應(yīng)該選擇一套他們認(rèn)為重要的規(guī)則來(lái)應(yīng)用,而不是采用默認(rèn)配置。 我發(fā)現(xiàn)使用默認(rèn)情況下啟用的規(guī)則的想法有點(diǎn)天真。 您的項(xiàng)目很有可能不是工具維護(hù)者在選擇其標(biāo)準(zhǔn)配置時(shí)考慮的項(xiàng)目。

此外,我相信當(dāng)您遇到不知道的語(yǔ)言功能時(shí),您應(yīng)該了解它。 當(dāng)您了解它時(shí),可以決定是否有更好的選擇。

實(shí)踐中的Java并發(fā)

關(guān)于JVM中并發(fā)的事實(shí)上的標(biāo)準(zhǔn)書是Brain Goetz編寫的Java Concurrency in Practice 。 它在幾個(gè)詳細(xì)級(jí)別上解釋了并發(fā)的各個(gè)方面。 如果您在Java(或不純的Scala)中使用任何形式的并發(fā),請(qǐng)確保您至少閱讀了這本出色的書的前三章,以對(duì)問(wèn)題有一個(gè)較高的了解。

翻譯自: https://www.javacodegeeks.com/2014/07/javas-volatile-modifier.html

java 揮發(fā)注解

總結(jié)

以上是生活随笔為你收集整理的java 挥发注解_Java的挥发性修饰符的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。