一、Java并發(fā)中什么是可見(jiàn)性
在Java并發(fā)編程中,可見(jiàn)性(Visibility)是指當(dāng)一個(gè)線程修改了共享變量的值后,其他線程能夠立即看到這個(gè)修改后的值。
在多線程環(huán)境下,每個(gè)線程都有自己的工作內(nèi)存,其中保存了該線程使用到的共享變量的副本。當(dāng)一個(gè)線程修改了共享變量的值時(shí),它首先會(huì)將修改后的值更新到自己的工作內(nèi)存中,然后再將該值刷新回主內(nèi)存中,以使其他線程能夠看到這個(gè)修改。
由于各個(gè)線程的工作內(nèi)存是相互獨(dú)立的,線程之間無(wú)法直接訪問(wèn)對(duì)方的工作內(nèi)存,因此就可能出現(xiàn)可見(jiàn)性問(wèn)題。當(dāng)一個(gè)線程修改了共享變量的值后,其他線程可能無(wú)法立即看到這個(gè)修改,導(dǎo)致出現(xiàn)所謂的“不可見(jiàn)”。
造成可見(jiàn)性問(wèn)題的主要原因是編譯器優(yōu)化和硬件的指令重排序。為了提高程序執(zhí)行的效率,編譯器和處理器可能會(huì)對(duì)指令進(jìn)行重新排序,這種重新排序在單線程環(huán)境下不會(huì)影響程序的最終結(jié)果,但在多線程環(huán)境下可能會(huì)導(dǎo)致可見(jiàn)性問(wèn)題。例如,一個(gè)線程在修改共享變量的值之后,由于重排序的存在,可能會(huì)將寫(xiě)操作的順序與其他指令進(jìn)行了調(diào)整,導(dǎo)致其他線程無(wú)法按照預(yù)期的順序讀取到該變量的最新值。
為了解決可見(jiàn)性問(wèn)題,Java提供了一些機(jī)制,例如使用volatile關(guān)鍵字和synchronized關(guān)鍵字。使用volatile關(guān)鍵字修飾的變量會(huì)告訴編譯器和處理器,每次訪問(wèn)該變量都必須從主內(nèi)存中讀取最新的值,并且對(duì)該變量的修改必須立即刷新回主內(nèi)存。而synchronized關(guān)鍵字則提供了一種加鎖機(jī)制,確保同一時(shí)刻只有一個(gè)線程可以訪問(wèn)被保護(hù)的代碼塊,從而避免了可見(jiàn)性問(wèn)題。