鎖
synchronized 原子性
不可中斷鎖,適合競爭不激烈,可讀性好
修改代碼塊:大括號括起來的代碼,作用于調(diào)用的對象
修飾方法:整個方法,作用于調(diào)用的對象
修飾靜態(tài)方法:整個靜態(tài)方法,作用于所有對象
-
修飾類:括號括起來的部分,作用于所有對象
代碼塊和方法屬于同一類(交替打印數(shù)字問題),靜態(tài)方法和類屬于同一類(打印完一個后在打印第二個)
Lock
- 可中斷鎖,多樣化同步,適合競爭時能維持常態(tài)
Atomic
- 競爭激烈時也能維持常態(tài),比Lock性能好;只能同步一個值
可見性
導(dǎo)致共享變量在線程間不可見的原因
- 線程交叉執(zhí)行
- 重排序結(jié)合線程交叉執(zhí)行
- 共享變量更新后的值沒有在工作內(nèi)存與主內(nèi)存間及時更新
JMM關(guān)于synchronized的兩條規(guī)定
- 線程解鎖前,必須把共享內(nèi)存的最新值刷新到主內(nèi)存
- 線程加鎖時,將清空工作內(nèi)存中共享變量的值,從而使用共享變量時需要從主內(nèi)存中重新讀取最新的值(注意:加鎖和解鎖是同一把鎖)
可見性-volatile
- 通過加入內(nèi)存屏障和禁止重排序優(yōu)化來實現(xiàn)
- 將volatile變量寫操作時,會在寫操作后加入一條store屏障指令,將本地內(nèi)存中的共享變量值刷新到主內(nèi)存
- 對volatile變量讀操作時,會在讀操作前加入一條load屏障指令,從主內(nèi)存中讀取共享變量
有序性
- java內(nèi)存模型中,允許編譯器和處理器對指令進行重排序,但是重排序過程不會影響到單線程程序的執(zhí)行,卻會影響到多線程并發(fā)執(zhí)行的正確性。
- volatile、synchronized、lock
有序性-hanpens-before原則 (8個原則)
- 程序次序規(guī)則:一個線程內(nèi),按照代碼順序,書寫在前面的操作先行發(fā)生與書寫在后面的操作
- 鎖定規(guī)則:一個unlock操作先行發(fā)生與后面對同一個鎖的lock操作(無論在單線程或者多線程中同一個鎖如果處于被鎖定狀態(tài),那么需要先unlock然后在進行l(wèi)ock)
- volatile變量規(guī)則:對一個變量的寫操作先行發(fā)生與后面對這個變量的讀操作(如果一個線程先去寫一個變量,另一個線程也去讀取這個變量,那么應(yīng)該是寫入操作先行發(fā)生于讀操作)-- 內(nèi)存屏障
- 傳遞規(guī)則:如果操作A先行發(fā)生于操作B,而操作B又先行發(fā)生與操作C,則可以得出操作A先行發(fā)生與操作C
- 線程啟動規(guī)則:Thread對象的start()方法先行發(fā)生于此線程的每一個動作
- 線程中斷原則:對線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測到中斷事件的發(fā)生;
- 線程終結(jié)規(guī)則:線程中所有的操作都先行發(fā)生于線程的終止檢測,我們可以通過Threa.join()方法結(jié)束、Thread.isAlive()的返回值手段檢測到線程已經(jīng)終止執(zhí)行;
- 對象終結(jié)規(guī)則:一個對象的初始化完成先行發(fā)生于他的finalize()方法的開始。