1、JUC--volatile 關鍵字-內存可見性
阿新 • • 發佈:2019-04-29
block rac 刷新 性問題 err bsp mage generated pre
Java JUC簡介
在 Java 5.0 提供了 java.util.concurrent (簡稱
JUC )包,在此包中增加了在並發編程中很常用
的實用工具類,用於定義類似於線程的自定義子
系統,包括線程池、異步 IO 和輕量級任務框架。
提供可調的、靈活的線程池。還提供了設計用於
多線程上下文中的 Collection 實現等
線程實例:
public class TestVoatile { public static void main(String[] args) { ThreadDemo td = new ThreadDemo();new Thread(td).start(); while(true){ if(td.isFlag()){ System.out.println("已啟動"); break; } } } } class ThreadDemo implements Runnable{ private boolean flag = false; public boolean isFlag(){return flag; } public void setFlag(boolean flag){ this.flag = flag; } @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } flag = true; System.out.println("flag:" + isFlag()); } }
此時的main函數中是有兩個線程的執行結果如下圖所示:
此時執行的是第一個線程
while循環並沒有執行
此時設計內存可見性的問題
共享數據
同時存在緩存的問題
此時線程1和main線程都有自己獨立的緩存
對於線程1來說首先需要要調用主存中的值,首先需要讀取值到線程1中
線程1讀取值之後,並且要向主存中進行改值
此時main線程到來,取出主存中的值
所以此時main線程中的flag=false
但是此時並沒有及時進行對主存進行修改值
此時使用線程睡眠:
ThreadDemo td = new ThreadDemo(); new Thread(td).start(); try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } while(true){ if(td.isFlag()){ System.out.println("已啟動"); break; } } }
內存可見性問題
多個線程操作共享數據問題,彼此不可見
可以使用同步鎖
在取值時進行刷新數據
public static void main(String[] args) { ThreadDemo td = new ThreadDemo(); new Thread(td).start(); while(true){ synchronized (td) { if(td.isFlag()){ System.out.println("已啟動"); break; } } } }
此時使用同步鎖機制,效率極低
每次都會進行判斷
如果一個正在使用數據,另一個線程就會等待
效率大大降低
volatile關鍵字:
當多個線程進行操作共享數據時,可以保證內存中的數據是可見的
可以理解成直接對主存中的數據進行操作
public class TestVoatile { public static void main(String[] args) { ThreadDemo td = new ThreadDemo(); new Thread(td).start(); while(true){ if(td.isFlag()){ System.out.println("已啟動"); break; } } } } class ThreadDemo implements Runnable{ private volatile boolean flag = false; public boolean isFlag(){ return flag; } public void setFlag(boolean flag){ this.flag = flag; } @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } flag = true; System.out.println("flag:" + isFlag()); } }
相對於synchronized:
Java 提供了一種稍弱的同步機制,即 volatile 變
量,用來確保將變量的更新操作通知到其他線程。
可以將 volatile 看做一個輕量級的鎖
前者是一種輕量級的同部策略
1、volatile不具有互斥性(synchronized具有鎖性值,只能有一個線程訪問)
2、volatile不具有原子性
1、JUC--volatile 關鍵字-內存可見性