日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

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

生活随笔

當(dāng)前位置: 首頁(yè) >

Java中的Volatile如何工作? Java中的volatile关键字示例

發(fā)布時(shí)間:2023/12/3 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中的Volatile如何工作? Java中的volatile关键字示例 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

如何在Java中使用Volatile關(guān)鍵字

在Java采訪中,什么是volatile變量以及何時(shí)在Java中使用volatile變量是Java 采訪中一個(gè)著名的多線程采訪問(wèn)題 。 盡管許多程序員都知道什么是volatile變量,但是他們?cè)诘诙糠稚鲜×?#xff0c;即在Java中何處使用volatile變量,因?yàn)閷?duì)Java的volatile缺乏清晰的認(rèn)識(shí)和動(dòng)手并不常見(jiàn)。 在本教程中,我們將通過(guò)提供Java中volatile變量的簡(jiǎn)單示例并討論何時(shí)在Java中使用volatile變量來(lái)解決這一差距。 無(wú)論如何,Java中的volatile關(guān)鍵字用作Java編譯器和Thread的指示符,它們不緩存此變量的值,而始終從主內(nèi)存讀取它。 因此,如果您想共享實(shí)現(xiàn)中原子的讀寫(xiě)操作所涉及的任何變量,例如,以int或boolean變量進(jìn)行讀寫(xiě),則可以將它們聲明為volatile變量。

從Java 5以及主要的變化(如自動(dòng)裝箱,枚舉,泛型和變量參數(shù))開(kāi)始,Java在Java內(nèi)存模型(JMM)中引入了一些更改,從而保證了從一個(gè)線程到另一個(gè)線程所做更改的可見(jiàn)性,也稱(chēng)為“事前發(fā)生”,可以解決一個(gè)線程中發(fā)生的內(nèi)存寫(xiě)入問(wèn)題可以“泄漏”并被另一個(gè)線程看到。

Java volatile關(guān)鍵字不能與方法或類(lèi)一起使用,而只能與變量一起使用。 Java volatile關(guān)鍵字還保證可見(jiàn)性和順序,在Java 5對(duì)任何volatile變量的寫(xiě)操作發(fā)生在對(duì)volatile變量的任何讀取之前。 順便說(shuō)一下,使用volatile關(guān)鍵字還可以防止編譯器或JVM對(duì)代碼重新排序或使它們脫離同步障礙。

為了了解Java中volatile關(guān)鍵字的示例,讓我們回到Java中的Singleton模式,并查看在Singleton中使用Volatile且在Java中不使用volatile關(guān)鍵字的情況下, 經(jīng)過(guò)雙重檢查的鎖定 。

/*** Java program to demonstrate where to use Volatile keyword in Java.* In this example Singleton Instance is declared as volatile variable to ensure* every thread see updated value for _instance.* * @author Javin Paul*/ public class Singleton{ private static volatile Singleton _instance; //volatile variable public static Singleton getInstance(){if(_instance == null){synchronized(Singleton.class){if(_instance == null)_instance = new Singleton();}}return _instance;}

如果仔細(xì)看一下代碼,您將能夠發(fā)現(xiàn):

1)我們只創(chuàng)建一次實(shí)例

2)我們?cè)诘谝粋€(gè)請(qǐng)求到來(lái)時(shí)懶洋洋地創(chuàng)建實(shí)例。

如果我們不使_instance變量可變?yōu)檎趧?chuàng)建Singleton實(shí)例的線程無(wú)法通信其他線程,則該實(shí)例已經(jīng)創(chuàng)建,直到它從Singleton塊中出來(lái),因此,如果線程A正在創(chuàng)建Singleton實(shí)例,并且創(chuàng)建丟失CPU之后,所有其他線程將無(wú)法看到_instance值不為null,他們將認(rèn)為_(kāi)instance值仍為null 。

為什么? 因?yàn)樽x取器線程未執(zhí)行任何鎖定,并且直到寫(xiě)入器線程脫離同步塊,否則內(nèi)存將不同步,并且_instance值也不會(huì)在主內(nèi)存中更新。 使用Java中的Volatile關(guān)鍵字,此問(wèn)題由Java自己處理,并且此類(lèi)更新將在所有閱讀器線程中可見(jiàn)。

因此,在摘要中,除了Java中的synced關(guān)鍵字外,volatile關(guān)鍵字還用于在線程之間傳遞內(nèi)存的內(nèi)容。

讓我們看一下Java中volatile關(guān)鍵字的另一個(gè)示例

在編寫(xiě)游戲的大部分時(shí)間中,我們使用變量bExit來(lái)檢查用戶是否按下了退出按鈕,該變量的值在事件線程中進(jìn)行了更新,并在游戲線程中進(jìn)行了檢查,因此,如果我們不對(duì)此變量使用volatile關(guān)鍵字,如果尚未在Java中同步,游戲線程可能會(huì)錯(cuò)過(guò)事件處理程序線程的更新。 Java中的volatile關(guān)鍵字保證了volatile變量的值將始終從主內(nèi)存中讀取,并且Java Memory模型中的“ before-before”關(guān)系將確保將內(nèi)存內(nèi)容傳遞給不同的線程。

private boolean bExit;while(!bExit) {checkUserPosition();updateUserPosition();}

在此代碼示例中,一個(gè)線程(游戲線程)可以緩存“ bExit ”的值,而不是每次都在其他線程(事件處理程序線程)之間更改該值時(shí)從主內(nèi)存中獲取它; 此線程將不可見(jiàn)。 在Java中將布爾變量“ bExit ”設(shè)置為volatile可以確保不會(huì)發(fā)生這種情況。

何時(shí)在Java中使用Volatile變量

學(xué)習(xí)volatile關(guān)鍵字最重要的事情之一就是了解何時(shí)在Java中使用volatile變量。 許多程序員都知道什么是volatile變量以及它如何工作,但他們從未真正將volatile用于任何實(shí)際目的。 這是幾個(gè)示例,以演示何時(shí)在Java中使用Volatile關(guān)鍵字:

1)如果要自動(dòng)讀寫(xiě)long和double變量,可以使用Volatile變量。 long和double都是64位數(shù)據(jù)類(lèi)型,默認(rèn)情況下,long和double的寫(xiě)入與原子和平臺(tái)無(wú)關(guān)。 許多平臺(tái)在long和double變量2步中執(zhí)行寫(xiě)操作,每步寫(xiě)32位,因此,線程可能會(huì)從兩次不同的寫(xiě)操作中看到32位。 您可以通過(guò)在Java中將long和double變量變?yōu)関olatile來(lái)避免此問(wèn)題。

2)在某些情況下,例如Visibility,可變變量可以用作Java中實(shí)現(xiàn)同步的替代方法。 使用volatile變量,可以確保一旦寫(xiě)入操作完成,所有讀取器線程都將看到volatile變量的更新值,而沒(méi)有volatile關(guān)鍵字,則不同的讀取器線程可能會(huì)看到不同的值。

3)volatile變量可用于通知編譯器特定字段將被多個(gè)線程訪問(wèn),這將阻止編譯器進(jìn)行任何重排序或任何類(lèi)型的優(yōu)化,而這在多線程環(huán)境中是不希望的。 如果沒(méi)有易失性變量,編譯器可以重新排序代碼,自由地緩存易失性變量的值,而不是始終從主內(nèi)存中讀取。 像下面的示例一樣,如果沒(méi)有volatile變量,可能會(huì)導(dǎo)致無(wú)限循環(huán)

private boolean isActive = thread; public void printMessage(){while(isActive){System.out.println("Thread is Active");} }

如果沒(méi)有volatile修飾符 ,則不能保證一個(gè)線程從另一線程看到isActive的更新值。 編譯器還可以自由緩存isActive的值,而不必在每次迭代中從主內(nèi)存中讀取它。 通過(guò)將isActive為volatile變量,可以避免這些問(wèn)題。

4)可以使用volatile變量的另一個(gè)地方是將雙重檢查鎖定固定為Singleton模式。 正如我們?cè)凇?為什么要使用Enum作為Singleton中討論”中所討論的那樣 ,在Java 1.4環(huán)境中,再次檢查鎖定已被破壞。

Java中Volatile關(guān)鍵字的要點(diǎn)

1. Java中的volatile關(guān)鍵字僅適用于變量,并且將volatile關(guān)鍵字與類(lèi)和方法一起使用是非法的。

2. Java中的volatile關(guān)鍵字保證volatile變量的值始終從主內(nèi)存中讀取,而不是從Thread的本地緩存中讀取。

3.在Java中,使用Java volatile關(guān)鍵字聲明的所有變量(包括long和double變量)的讀寫(xiě)操作都是原子的。

4.在Java中對(duì)變量使用volatile關(guān)鍵字可降低內(nèi)存一致性錯(cuò)誤的風(fēng)險(xiǎn),因?yàn)樵贘ava中對(duì)volatile變量的任何寫(xiě)入都會(huì)與該變量的后續(xù)讀取建立先發(fā)生后關(guān)系。

5.從Java 5到volatile變量的更改始終對(duì)其他線程可見(jiàn)。 而且,這還意味著,當(dāng)線程在Java中讀取volatile變量時(shí),它不僅會(huì)看到volatile變量的最新更改,還會(huì)看到導(dǎo)致更改的代碼的副作用。

6.讀和寫(xiě)是原子的,因?yàn)榧词共辉贘ava中使用volatile關(guān)鍵字,引用變量也適用于大多數(shù)原始變量(除了long和double以外的所有類(lèi)型)。

7.對(duì)Java中的volatile變量的訪問(wèn)永遠(yuǎn)不會(huì)有阻塞的機(jī)會(huì),因?yàn)槲覀冎贿M(jìn)行簡(jiǎn)單的讀或?qū)懖僮?#xff0c;因此與同步塊不同,我們永遠(yuǎn)不會(huì)保持任何鎖或等待任何鎖 。

8.作為對(duì)象引用的Java volatile變量可以為null。

9. Java volatile關(guān)鍵字不是原子的,它的普遍誤解是在聲明volatile ++將是原子的之后,要使操作原子化,您仍然需要確保使用Java中的同步方法或塊進(jìn)行獨(dú)占訪問(wèn)。

10.如果一個(gè)變量沒(méi)有在多個(gè)線程之間共享,則不需要對(duì)該變量使用volatile關(guān)鍵字。

Java中sync和volatile關(guān)鍵字之間的區(qū)別

可變和同步之間的區(qū)別是在多線程和并發(fā)訪問(wèn)中提出的另一個(gè)流行的Java核心問(wèn)題 。 請(qǐng)記住,volatile不能替代synced關(guān)鍵字,但在某些情況下可以用作替代。 這是Java中volatile和sync關(guān)鍵字之間的一些區(qū)別。

1. Java中的volatile關(guān)鍵字是字段修飾符,而sync則修改代碼塊和方法。

2.同步獲取并釋放對(duì)監(jiān)視器的Java volatile關(guān)鍵字的鎖定,不需要這樣做。

3.在同步的情況下,可以阻止Java中的線程等待任何監(jiān)視器,而Java中的volatile關(guān)鍵字則不會(huì)。

4.同步方法比Java中的volatile關(guān)鍵字對(duì)性能的影響更大。

5.由于在Java中volatile關(guān)鍵字僅同步一個(gè)可變的螺紋存儲(chǔ)器和“之間的值main ”存儲(chǔ)器而同步進(jìn)行同步線程存儲(chǔ)器和“之間的所有變量的值main ”存儲(chǔ)器和鎖定和釋放的監(jiān)視器來(lái)引導(dǎo)。 由于這個(gè)原因,Java中的synced關(guān)鍵字可能比volatile具有更多的開(kāi)銷(xiāo)。

6.您無(wú)法在null對(duì)象上同步,但是Java中的volatile變量可能為null。

7.在Java 5中,寫(xiě)入volatile字段具有與監(jiān)視器發(fā)行版相同的存儲(chǔ)效果,而從volatile字段讀取具有與監(jiān)視器獲取相同的存儲(chǔ)效果。

簡(jiǎn)而言之,Java中的volatile關(guān)鍵字不能替代同步塊或方法,但是在某些情況下非常方便,并且可以節(jié)省Java中使用同步所帶來(lái)的性能開(kāi)銷(xiāo)。 如果您想了解更多有關(guān)volatile的知識(shí),我還建議您在此處仔細(xì)閱讀有關(guān)Java內(nèi)存模型的常見(jiàn)問(wèn)題解答,以很好地解釋操作之前發(fā)生的事情。

翻譯自: https://www.javacodegeeks.com/2018/03/volatile-java-works-example-volatile-keyword-java.html

總結(jié)

以上是生活随笔為你收集整理的Java中的Volatile如何工作? Java中的volatile关键字示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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