兩個概念:
可見性
在一個線程中修改了變量的值 該變量能立刻回顯到主線程中,確保其他線程也能看待該變量的修改
原子性
代碼執(zhí)行會一步到位谣旁,不會被其他操作影響到當前
1.volatile
只能用來修飾變量趴腋,常用于修飾可能同時被多個線程同時訪問的變量
volatile 可以保證變量的有序性(底層禁用指令重排序) 但不具有原子性
被volatile修飾的變量改變后會立即同步到主內(nèi)存保證變量的可見性
在雙重檢查單例模式中加volatile的原因:
在 instance = new Singleton() 初始化過程中 會被分成三步執(zhí)行
1.給Singleton的實例分配內(nèi)存
2.調(diào)用Singleton()的構造函數(shù)踊淳,初始化成員字段
3.將instance對象指向分配的內(nèi)存空間
由于Java編譯器允許處理器亂序執(zhí)行肆氓,上述順序可能是1-2-3 或1-3-2
在1-3-2時若在線程A中執(zhí)行完3 22位執(zhí)行時 切換到線程B 此時instance對象已不為空 所以線程B直接取用instance 成員字段未初始化 在使用時會發(fā)生錯誤 DCL失效
而添加volatile 禁用了變量的指令重排序保證了順序執(zhí)行且使得instance每次都從主內(nèi)存中讀取
擴展:
解決 多核CPU 高速緩存中數(shù)據(jù)不同步問題
2.synchronize
synchronize還可以保證變量的同步性和原子性
在jvm虛擬機中使用Monitor對象來實現(xiàn)方法同步和代碼塊同步去枷。
Monitor本質(zhì)是使用互斥鎖來實現(xiàn)竭望,保證同一時間只有一個線程來訪問該對象
線程在加鎖時工作順序:
先清空工作內(nèi)存→在主內(nèi)存中拷貝最新變量的副本到工作內(nèi)存→執(zhí)行完代碼→將更改后的共享變量的值刷新到主內(nèi)存中→釋放互斥鎖