1、上圖多線程
2、Java內存模型的設計目的併發
1.屏蔽掉不一樣硬件、操做系統之間的內存訪問差別,實現Java程序在各類平臺下達到一致的內存訪問效果(Java口號:write once,run anywhere)優化
2.定義程序中線程共享區域(堆、方法區)的變量訪問規則(存在線程競爭問題)操作系統
3、內存交互指令以及使用限制線程
8個交互指令:設計
1.主內存變量操做指令:lock、unlock、read、write3d
2.線程工做內存變量操做指令:load、use、assign、storeblog
使用限制:排序
1.read指令與load指令結合使用,store指令與write指令結合使用。不容許變量從主內存read後工做內存不load,以及從工做內存發起store後主內存不write內存
2.執行引擎assign變量副本後需當即store,store以後需當即write到變量,所以assign->store->write可列爲一組順序指令,執行引擎use變量以前要求從工做內存load變量,load以前要求從主內存read變量到工做內存副本,所以read->load->use可列爲一組順序指令
3.lock與unlock指令必須成對出現,且同一時刻只容許一條線程對一個變量進行lock操做,該線程可lock屢次該變量,須要對應次unlock。當變量被lock後,須要清空所有工做內存中此變量副本的值,當執行引擎下一次使用該變量時,需執行read->load->use指令;變量執行unlock指令以前,必須先把變量同步回主內存中,需執行assign->store->write指令。
volatile基於指令的操做規則
1.volatile修飾的變量被使用前必須從主內存刷新最新的值,保證能看見其餘線程的修改。即read-load-use
2.volatile修飾的變量賦值後必須馬上同步回主內存,以保證其餘線程能看到本身的修改。即assign-store-write
3.volatile修飾的變量禁止指令重排序優化
結合以上思考:爲何被volatile修飾的變量多線程寫入時會不許確?
兩個線程操做a變量,正常結果應該是a=2,但實際結果是a=1。因爲a++操做不具有原子性,致使併發問題。
所謂的可見性是指,此時a=1了,對其餘將對a變量操做的線程(變量a未進入執行引擎進行處理)來講,會實時讀取到這個值。