Java多线程_1_Java内存模型_内存模型的3大特性
Java內存模型:
內存分布情況及其關系:
主內存:Java內存模型規(guī)定所有的變量都保存在主內存中
工作內存:每個線程都有自己的工作內存,保存了該線程使用到的變量的主內存副本拷貝
主內存與工作內存的關系:
線程對變量的所有操作都必須在自己的工作內存中進行,不能直接讀寫主內存中的變量
不同線程之間無法直接訪問對方工作內存中的變量
線程間變量值的傳遞均需要通過主內存來完成
內存交互操作:
java內存模型定義了8個操作完成主內存與工作內存的交互操作
1.read: 把變量從主內存讀取到工作內存中 2.load: 在read執(zhí)行后, 把read得到的值存入工作內存中 3.use: 把工作內存中一個變量值傳遞給執(zhí)行引擎 4.assign: 把一個執(zhí)行引擎接收的數(shù)據(jù)復制給工作內存變量 5.store: 把工作內存中的一個變量的值傳送到主內存 6.write: 在store執(zhí)行后, 把store得到的值放入主內存的變量中 7.lock: 作用于主內存的變量 8.unclock注:
read-load,store-write必須順序執(zhí)行,不需要連續(xù)執(zhí)行(read a,read a,load b,load b),不可單獨出現(xiàn).
不允許一個線程丟棄它最近的assign的操作,即變量在工作內存中改變了之后必須把該變化同步到主內存中
不允許一個線程無原因地把數(shù)據(jù)從線程的工作內存同步回主內存中
一個新變量只能在主內存中誕生,不允許在工作內存中直接使用一個未被初始化的變量
一個變量在同一時刻只允許一條線程對其lock操作,但lock操作可以被同一條線程執(zhí)行多次,多次執(zhí)行l(wèi)ock后,只有執(zhí)行相同次數(shù)的unclock,變量才能解鎖
如果對一個變量執(zhí)行l(wèi)ock操作,將會清空工作內存 中此變量的值,在執(zhí)行引擎使用這個變量前,需要重新執(zhí)行l(wèi)oad/assign來初始化變量
如果一個變量沒被lock鎖定,則不允許對它執(zhí)行unclock,unclock也一致
對變量執(zhí)行unclock操作之前,必須把此變量同步到主內存中(執(zhí)行store/write)
原子性:
互斥同步機制:
1.JVM實現(xiàn)的synchronized:同步一個代碼塊:public void f(){synchronized(this){.......}} //只能作用于同一個對象, 不同的對象不同進行同步, 例如: 如果同步一個賬戶,兩個人同時操作一個賬戶,賬戶加鎖即可同步, 對于不同的賬戶不需要同步, 二者沒有任何關系, 也就沒有同步這一說法同步一個方法與同步代碼塊一致只能作用于同一個對象:public synchronized void f(){.....}同步一個類,作用于整個類,兩個線程調用同一個類的不同對象也會產生同步:public void f(){synchronized (SynchronizedExample.class){.........}}同步一個靜態(tài)方法,作用于整個類public synchronized static void f(){....}2.JDK實現(xiàn)的ReentrantLock //java.util.concurrent(J.U.C)包中的鎖public class LockTest{private Lock lock = new ReentrantLock();public void f(){lock.lock();try{.......}finally{lock.unlock();//釋放鎖,避免死鎖}}}上述二者的性能現(xiàn)在大致相同
ReentrantLock與synchronized的區(qū)別:
在ReentrantLock中當持有鎖的線程長期不釋放鎖的時候, 正在等待的線程可以選擇放棄, 改為處理其他事, synchronized不行
公平鎖: 多個線程等待同一個鎖, 必須按照申請鎖的時間順序獲得鎖, synchronized中非公平鎖,ReentrantLock也是非公平的, 但也可以是公平的
ReentrantLock可以同時綁定多個Condition對象
注: 除非使用ReentrantLock的高級功能, 否則優(yōu)先使用synchronized, ReentrantLock不是所有的JDK都支持, 使用synchronized不用擔心沒釋放鎖而導致死鎖問題, JVM會釋放鎖
原子性總結
synchronized的修飾對象
修飾代碼塊:大括號括起來,作用于對象
修飾方法:方法名前使用, 作用于對象在方法內部使用synchronized代碼塊,與修飾方法時效果是一致的
修飾靜態(tài)方法:整個靜態(tài)方法,作用于所有對象
修飾類:類名前添加,作用于所有對象
注:
1.作用于對象時,不同調用對象之間不影響 2.使用synchronized的父類(synchronized不屬于方法聲明的一部分),子類繼承后需要對其方法重新添加synchronized修飾,不然不能使用同步 特點:synchronized:不可中斷鎖,適用于競爭不激烈,可讀性好的場景Lock:可中斷鎖,多樣化同步,競爭激烈時能維持常態(tài)Atomic:競爭激烈時能維持常態(tài),比Lock性能好可見性:
定義: 指當多個線程訪問同一個變量時,一個線程修改了這個變量的值,其他線程能夠立即看得到修改的值。
即: 當共享變量被修改后, 在其他線程修改之前, 會被立馬同步到主內存中
導致共享變量在線程中不可見原因:
Java多線程的可見性操作
在多線程環(huán)境下,一個線程對共享變量的操作對其他線程是不可見的。
Java提供了volatile來保證可見性,當一個變量被volatile修飾后,表示著線程本地內存無效,當一個線程修改共享變量后他會立即被更新到主內存中,其他線程讀取共享變量時,會直接從主內存中讀取。
synchronize和Lock都可以保證可見性。synchronized和Lock能保證同一時刻只有一個線程獲取鎖然后執(zhí)行同步代碼,并且在釋放鎖之前會將對變量的修改刷新到主存當中, 以此保證可見性。
synchronized與volatile可見性操作細節(jié):
synchronized的可見性:1.線程解鎖前(線程執(zhí)行完同步模塊之前),必須把共享變量的最新值刷新到主內存(從工作內存中把值放入主內存)2.線程加鎖的時候,必須先清空工作內存中上次存儲的共享變量的值,然后再從主內存重新讀取最新的值(加鎖與解鎖是對同一把鎖來說) volatile的可見性:1.對volatile修飾的變量進行寫操作的時候,會在寫操作之后,加StoreStore屏障指令,將工作內存中變量值刷新到主內存中共享變量2.對volatile修飾的變量進行讀操作的時候,會在讀操作之前,加StoreLoad屏障指令,從主內存讀取共享變量,載入工作內存(也就把以前工作內存存儲的值覆蓋) final的可見性:final: 被final修飾的變量在構造函數(shù)中被初始化且沒有發(fā)生this逃逸,其他線程就能看見final注:
volatile的寫操作:
StoreStore屏障禁止volatile指令上面的普通寫和下面的volatile寫操作重排序
StoreLoad屏障防止volatile寫操作與之后volatile讀寫操作的指令重排
volatile的讀操作:
在插入LoadLoad屏障的位置, 禁止該指令前以及該指令后的volatile的讀寫重排序操作
volatile不具有原子性, 不是線程安全的, 只適合于作為狀態(tài)標記量, 對變量的寫操作不依賴于當前值
有序性:
定義:即程序執(zhí)行的順序按照代碼的先后順序執(zhí)行, 在本線程中觀察, 所有的操作都是有序的
需要注意的是:
從其他線程看本線程中會發(fā)現(xiàn)所有的操作都是無序的, jvm對每個線程都會進行指令重排, 且重排都會不一樣, 在多線程的情況下, 指令重排將會出錯, 一般采用volatile/synchronized修飾, 不會出現(xiàn)指令重排, 確保每個時刻都只有一個線程在執(zhí)行.
先行發(fā)生原則:
1.單一線程原則:單個線程內, 程序前面的操作先行發(fā)生與后面的操作
2.管程鎖定原則:一個unclock操作先行發(fā)生于后面對同一個所的lock操作,必須釋放鎖后,才能對對象重新加鎖
3.volatile變量原則:對一個變量的寫操作先行發(fā)生于后面對這個變量的讀的操作
4.線程啟動:Thread對象的start操作先行發(fā)生于此線程的每一個操作
5.線程加入規(guī)則: Thread對象的結束先行發(fā)生于join()的返回
6.線程中斷原則: 對線程interrupt()的調用先行發(fā)生于被中斷線程代碼檢測到的中斷時間的發(fā)生, 可以通過interrupt檢測是否有中斷發(fā)生
7.對象終結規(guī)則: 一個對象的初始化(從構造函數(shù)結束開始)先行發(fā)生于它的finalize方法的開始
8.傳遞性: A比B先發(fā)生, B比C先發(fā)生, 則A比C先發(fā)生
上面有錯, 還請指出, 如果認為我寫的還不錯, 還請點個贊, 多多支持一下, O(∩_∩)O~~
總結
以上是生活随笔為你收集整理的Java多线程_1_Java内存模型_内存模型的3大特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python层次聚类_python实现层
- 下一篇: python写xml文件_用python