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