在Java中實現(xiàn)可見性(visibility)的主要方法詳解
可見性 visibility
在Java中,實現(xiàn)可見性(visibility)的主要方法是使用關(guān)鍵字volatile和使用鎖(如synchronized關(guān)鍵字或 java.util.concurrent包中的鎖)來確保對共享變量的修改在多線程環(huán)境中能夠正確地被其他線程所觀察到。
下面詳細(xì)說明這兩種方法,并附帶代碼演示。
1.使用volatile關(guān)鍵字:
volatile是一種輕量級的同步機制,用于告訴JVM對被修飾的變量不進(jìn)行緩存,直接從主內(nèi)存中讀取和寫入數(shù)據(jù)。
這樣可以確保當(dāng)一個線程修改了變量的值時,其他線程能夠立即看到這個變化,而不是使用緩存中的舊值。
public class VolatileVisibilityExample { private volatile boolean flag = false; public void setFlag(boolean value) { flag = value; } public void checkFlag() { while (!flag) { // Busy waiting until the flag becomes true } System.out.println("Flag is now true!"); } public static void main(String[] args) { VolatileVisibilityExample example = new VolatileVisibilityExample(); new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } example.setFlag(true); }).start(); new Thread(() -> { example.checkFlag(); }).start(); } }
在上面的例子中,我們創(chuàng)建了一個VolatileVisibilityExample類,其中的flag變量被聲明為volatile。
第一個線程在啟動后會等待1秒鐘然后將flag設(shè)置為true,而第二個線程在flag變?yōu)閠rue之前會一直進(jìn)行忙等待(busy waiting)。
由于flag是volatile的,第二個線程能夠看到第一個線程對flag的修改,并在flag變?yōu)閠rue時結(jié)束忙等待。
2.使用鎖:
另一種實現(xiàn)可見性的方法是使用鎖,通過synchronized關(guān)鍵字或者java.util.concurrent包中的鎖機制來保護(hù)對共享變量的訪問。
public class LockVisibilityExample { private boolean flag = false; private final Object lock = new Object(); public void setFlag(boolean value) { synchronized (lock) { flag = value; } } public void checkFlag() { synchronized (lock) { while (!flag) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println("Flag is now true!"); } public static void main(String[] args) { LockVisibilityExample example = new LockVisibilityExample(); new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } example.setFlag(true); synchronized (example.lock) { example.lock.notifyAll(); } }).start(); new Thread(() -> { example.checkFlag(); }).start(); } }
在上面的例子中,我們創(chuàng)建了一個LockVisibilityExample類,其中使用了一個名為lock的對象作為鎖。
在setFlag和checkFlag方法中,我們使用synchronized關(guān)鍵字來保護(hù)對flag的訪問。
第一個線程設(shè)置flag為true并通過synchronized塊的notifyAll()方法通知第二個線程,而第二個線程則在flag變?yōu)閠rue之前一直等待,并在被通知后結(jié)束等待。
這兩種方法都可以實現(xiàn)可見性,但使用volatile更為簡單和輕量級。
然而,在某些情況下,使用鎖可能會更有優(yōu)勢,例如需要進(jìn)行更復(fù)雜的操作或需要更精細(xì)地控制對共享資源的訪問。
到此這篇關(guān)于在Java中實現(xiàn)可見性(visibility)的主要方法詳解的文章就介紹到這了,更多相關(guān)Java中實現(xiàn)可見性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于SpringBoot和Dify實現(xiàn)流式響應(yīng)輸出
這篇文章主要為大家詳細(xì)介紹了如何基于SpringBoot和Dify實現(xiàn)流式響應(yīng)輸出效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2025-03-03java中線程的sleep()方法和yield()方法的區(qū)別
本文主要介紹了java中線程的sleep()方法和yield()方法的區(qū)別,Thread類的sleep()方法使線程休眠指定時間,不釋放鎖,而yield()提示調(diào)度器當(dāng)前線程愿意讓出CPU資源,不保證立即切換線程,感興趣的可以了解一下2024-10-10Elasticsearch?Recovery索引分片分配詳解
這篇文章主要為大家介紹了關(guān)于Elasticsearch的Recovery索引分片分配詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2022-04-04Java多線程程序中synchronized修飾方法的使用實例
synchronized關(guān)鍵字主要北用來進(jìn)行線程同步,這里我們主要來演示Java多線程程序中synchronized修飾方法的使用實例,需要的朋友可以參考下:2016-06-06SpringBoot對接clerk實現(xiàn)用戶信息獲取功能
Clerk是一個提供身份驗證和用戶管理的服務(wù),可以幫助開發(fā)者快速集成這些功能,下面我們就來看看如何使用Spring?Boot對接Clerk實現(xiàn)用戶信息的獲取吧2025-02-02Springboot實現(xiàn)動態(tài)定時任務(wù)管理的示例代碼
最近在做spring boot項目開發(fā)中,由于使用@EnableScheduling注解和@Scheduled注解來實現(xiàn)的定時任務(wù),只能靜態(tài)的創(chuàng)建定時任務(wù),不能動態(tài)修改、添加、刪除、啟/停任務(wù),下面通過本文給大家介紹Springboot實現(xiàn)動態(tài)定時任務(wù)管理的方法,感興趣的朋友跟隨小編一起看看吧2023-07-07