涓€銆丣MM
JMM 鍗?Java Memory Model锛屽畠瀹氫箟浜嗕富瀛樸€佸伐浣滃唴瀛樻娊璞℃蹇碉紝搴曞眰瀵瑰簲鐫€ CPU 瀵勫瓨鍣ㄣ€佺紦瀛樸€佺‖浠跺唴瀛樸€丆PU 鎸囦护浼樺寲绛夈€?br> JMM 浣撶幇鍦ㄤ互涓嬪嚑涓柟闈?/p>
- 鍘熷瓙鎬?- 淇濊瘉鎸囦护涓嶄細鍙楀埌绾跨▼涓婁笅鏂囧垏鎹㈢殑褰卞搷
- 鍙鎬?- 淇濊瘉鎸囦护涓嶄細鍙?cpu 缂撳瓨鐨勫奖鍝?/li>
- 鏈夊簭鎬?- 淇濊瘉鎸囦护涓嶄細鍙?cpu 鎸囦护骞惰浼樺寲鐨勫奖鍝?/li>
涓诲瓨瀵瑰簲鍫嗗唴瀛橈紝宸ヤ綔鍐呭瓨瀵瑰簲鏍堝唴瀛橈紝绾跨▼闇€瑕佷粠涓诲瓨璇绘暟鎹紝鐒跺悗鍦ㄥ伐浣滃唴瀛樹腑璁$畻锛屾渶鍚庡啓鍥炰富瀛樸€?/p>
浜屻€佸彲瑙佹€?/h2>
@Slf4j
public class TestVisible {
static boolean runFlag = true;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while (runFlag){
}
log.debug("鍋滄寰幆浜?);
});
t.start();
Thread.sleep(1000);
log.debug("鍋滄t1");
runFlag = false;
}
}
17:28:19.008 [main] DEBUG juc.visibility.TestVisible - 鍋滄t1
@Slf4j
public class TestVisible {
static boolean runFlag = true;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while (runFlag){
}
log.debug("鍋滄寰幆浜?);
});
t.start();
Thread.sleep(1000);
log.debug("鍋滄t1");
runFlag = false;
}
}
17:28:19.008 [main] DEBUG juc.visibility.TestVisible - 鍋滄t1
1.鍒濆鐘舵€侊紝 t 绾跨▼鍒氬紑濮嬩粠涓诲唴瀛樿鍙栦簡 run 鐨勫€煎埌宸ヤ綔鍐呭瓨
2.鍥犱负 t 绾跨▼瑕侀绻佷粠涓诲唴瀛樹腑璇诲彇 run 鐨勫€硷紝JIT 缂栬瘧鍣ㄤ細灏?run 鐨勫€肩紦瀛樿嚦鑷繁宸ヤ綔鍐呭瓨涓殑楂橀€熺紦瀛樹腑锛屽噺灏戝涓诲瓨涓?run 鐨勮闂紝鎻愰珮鏁堢巼
3.1 绉掍箣鍚庯紝main 绾跨▼淇敼浜?run 鐨勫€硷紝骞跺悓姝ヨ嚦涓诲瓨锛岃€?t 鏄粠鑷繁宸ヤ綔鍐呭瓨涓殑楂橀€熺紦瀛樹腑璇诲彇杩欎釜鍙橀噺鐨勫€硷紝缁撴灉姘歌繙鏄棫鍊?/p>
瑙e喅鏂瑰紡涓€锛歷olatile(鎺ㄨ崘)
volatile锛氬畠鍙互鐢ㄦ潵淇グ鎴愬憳鍙橀噺鍜岄潤鎬佹垚鍛樺彉閲忥紝鍙互閬垮厤绾跨▼浠庤嚜宸辩殑宸ヤ綔缂撳瓨涓煡鎵惧彉閲忕殑鍊硷紝蹇呴』鍒颁富瀛樹腑鑾峰彇瀹冪殑鍊硷紝绾跨▼鎿嶄綔 volatile 鍙橀噺閮芥槸鐩存帴鎿嶄綔涓诲瓨銆?/p>
@Slf4j
public class TestVisible {
static volatile boolean runFlag = true;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while (runFlag){
}
log.debug("鍋滄寰幆浜?);
});
t.start();
Thread.sleep(1000);
log.debug("鍋滄t1");
runFlag = false;
}
}
18:33:39.386 [main] DEBUG juc.visibility.TestVisible - 鍋滄t1
18:33:39.389 [Thread-0] DEBUG juc.visibility.TestVisible - 鍋滄寰幆浜?
瑙e喅鏂瑰紡浜岋細synchronized
@Slf4j
public class TestVisible1 {
static boolean runFlag = true;
final static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while (true){
synchronized (lock){
if(!runFlag){
break;
}
}
}
log.debug("鍋滄寰幆浜?);
});
t.start();
Thread.sleep(1000);
log.debug("鍋滄t1");
synchronized (lock){
runFlag = false;
}
}
}
绾跨▼杩涘叆synchronized浠g爜鍓嶏紝浼氳幏寰楅攣锛屾竻绌哄伐浣滃唴瀛橈紝浠庝富鍐呭瓨鎷疯礉鍏变韩鍙橀噺鏈€鏂扮殑鍊煎埌宸ヤ綔鍐呭瓨鎴愪负鍓湰锛屾墽琛屼唬鐮侊紝灏嗕慨鏀瑰悗鐨勫壇鏈€煎埛鏂板洖涓诲唴瀛樹腑锛岄噴鏀鹃攣銆?/p>
鍙鎬?vs 鍘熷瓙鎬?/h4>
鍙鎬т繚璇佺殑鏄湪澶氫釜绾跨▼涔嬮棿锛屼竴涓嚎绋嬪 volatile 鍙橀噺鐨勪慨鏀瑰鍙︿竴涓嚎绋嬪彲瑙侊紝 浣嗕笉鑳戒繚璇佸師瀛愭€э紝浠呯敤鍦ㄤ竴涓啓绾跨▼锛屽涓绾跨▼鐨勬儏鍐碉細
涓婁緥浠庡瓧鑺傜爜鐞嗚В鏄繖鏍风殑锛?/p>
getstatic run // 绾跨▼ t 鑾峰彇 run true
getstatic run // 绾跨▼ t 鑾峰彇 run true
getstatic run // 绾跨▼ t 鑾峰彇 run true
getstatic run // 绾跨▼ t 鑾峰彇 run true
putstatic run // 绾跨▼ main 淇敼 run 涓?false锛?浠呮涓€娆?
getstatic run // 绾跨▼ t 鑾峰彇 run false
涓や釜绾跨▼锛氫竴涓?i++ 涓€涓?i-- 锛屽彧鑳戒繚璇佺湅鍒版渶鏂板€硷紝涓嶈兘瑙e喅鎸囦护浜ら敊鐨勫師瀛愭€ч棶棰橈細
// 鍋囪i鐨勫垵濮嬪€间负0
getstatic i // 绾跨▼2-鑾峰彇闈欐€佸彉閲廼鐨勫€?绾跨▼鍐卛=0
getstatic i // 绾跨▼1-鑾峰彇闈欐€佸彉閲廼鐨勫€?绾跨▼鍐卛=0
iconst_1 // 绾跨▼1-鍑嗗甯搁噺1
iadd // 绾跨▼1-鑷 绾跨▼鍐卛=1
putstatic i // 绾跨▼1-灏嗕慨鏀瑰悗鐨勫€煎瓨鍏ラ潤鎬佸彉閲廼 闈欐€佸彉閲廼=1
iconst_1 // 绾跨▼2-鍑嗗甯搁噺1
isub // 绾跨▼2-鑷噺 绾跨▼鍐卛=-1
putstatic i // 绾跨▼2-灏嗕慨鏀瑰悗鐨勫€煎瓨鍏ラ潤鎬佸彉閲廼 闈欐€佸彉閲廼=-1
synchronized 璇彞鍧楁棦鍙互淇濊瘉浠g爜鍧楃殑鍘熷瓙鎬э紝涔熷悓鏃朵繚璇佷唬鐮佸潡鍐呭彉閲忕殑鍙鎬с€備絾缂虹偣鏄痵ynchronized 鏄睘浜庨噸閲忕骇鎿嶄綔锛屾€ц兘鐩稿鏇翠綆
涓夈€乿olatile搴旂敤
浣跨敤volatile鏀硅繘涓ら樁娈电粓姝細
@Slf4j
public class TestVolatile {
public static void main(String[] args) throws InterruptedException {
TwoPhaseTerminate twoPhaseTerminate = new TwoPhaseTerminate();
twoPhaseTerminate.start();
Thread.sleep(4000);
twoPhaseTerminate.stop();
}
}
@Slf4j
class TwoPhaseTerminate {
private Thread monitorThread;
private volatile boolean stopFlag = false;
/**
* 鍚姩绾跨▼
*/
public void start() {
monitorThread = new Thread(() -> {
while (true) {
// 鏄惁琚墦鏂?
if (stopFlag) {
log.debug("鏂欑悊鍚庝簨");
break;
}
try {
Thread.sleep(1000);
log.debug("鎵ц鐩戞帶璁板綍");
} catch (InterruptedException e) {
//涓嶉渶瑕佽€冭檻鎵撴柇鏍囪锛屽洜涓轰娇鐢ㄧ殑鏄痵topFlag鏉ユ帶鍒剁殑
e.printStackTrace();
}
}
}, "monitor");
monitorThread.start();
}
/**
* 鍋滄绾跨▼
*/
public void stop() {
stopFlag = true;
//闃叉绾跨▼鍒氬ソ鍦ㄦ墽琛宻leep鐨勮繃绋嬩腑琚仠姝紝鐢╥nterrupt鏉ョ粓姝leep
monitorThread.interrupt();
}
}
19:31:36.199 [monitor] DEBUG juc.visibility.TwoPhaseTerminate - 鎵ц鐩戞帶璁板綍
19:31:37.205 [monitor] DEBUG juc.visibility.TwoPhaseTerminate - 鎵ц鐩戞帶璁板綍
19:31:38.206 [monitor] DEBUG juc.visibility.TwoPhaseTerminate - 鎵ц鐩戞帶璁板綍
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at juc.visibility.TwoPhaseTerminate.lambda$start鍥涖€佸悓姝ユā寮忎箣Balking
(TestVolatile.java:43)
at java.lang.Thread.run(Thread.java:748)
19:31:39.195 [monitor] DEBUG juc.visibility.TwoPhaseTerminate - 鏂欑悊鍚庝簨
@Slf4j
public class TestVolatile {
public static void main(String[] args) throws InterruptedException {
TwoPhaseTerminate twoPhaseTerminate = new TwoPhaseTerminate();
twoPhaseTerminate.start();
twoPhaseTerminate.start();
twoPhaseTerminate.start();
Thread.sleep(4000);
twoPhaseTerminate.stop();
}
}
@Slf4j
class TwoPhaseTerminate {
private Thread monitorThread;
private volatile boolean stopFlag = false;
/**
* 鐢ㄤ竴涓爣璁颁綅鏉ユ爣璁板彧闇€瑕佹墽琛屼竴閬嶇殑浠g爜涓嶉噸澶嶆墽琛?
*/
private boolean startFlag = false;
/**
* 鍚姩绾跨▼
*/
public void start() {
synchronized (this) {
if (startFlag) {
return;
}
startFlag = true;
}
monitorThread = new Thread(() -> {
while (true) {
// 鏄惁琚墦鏂?
if (stopFlag) {
log.debug("鏂欑悊鍚庝簨");
break;
}
try {
Thread.sleep(1000);
log.debug("鎵ц鐩戞帶璁板綍");
} catch (InterruptedException e) {
//涓嶉渶瑕佽€冭檻鎵撴柇鏍囪锛屽洜涓轰娇鐢ㄧ殑鏄痵topFlag鏉ユ帶鍒剁殑
e.printStackTrace();
}
}
}, "monitor");
monitorThread.start();
}
/**
* 鍋滄绾跨▼
*/
public void stop() {
stopFlag = true;
//闃叉绾跨▼鍒氬ソ鍦ㄦ墽琛宻leep鐨勮繃绋嬩腑琚仠姝紝鐢╥nterrupt鏉ョ粓姝leep
monitorThread.interrupt();
}
}
Balking锛堢姽璞級妯″紡鐢ㄥ湪涓€涓嚎绋嬪彂鐜板彟涓€涓嚎绋嬫垨鏈嚎绋嬪凡缁忓仛浜嗘煇涓€浠剁浉鍚岀殑浜嬶紝閭d箞鏈嚎绋嬪氨鏃犻渶鍐嶅仛浜嗭紝鐩存帴缁撴潫杩斿洖銆傪煓凁煓凁煓?br> demo1:
19:54:17.437 [monitor] DEBUG juc.visibility.TwoPhaseTerminate - 鎵ц鐩戞帶璁板綍
19:54:18.441 [monitor] DEBUG juc.visibility.TwoPhaseTerminate - 鎵ц鐩戞帶璁板綍
19:54:19.443 [monitor] DEBUG juc.visibility.TwoPhaseTerminate - 鎵ц鐩戞帶璁板綍
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at juc.visibility.TwoPhaseTerminate.lambda$startpublic class Singleton {
private static Singleton INSTANCE = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (INSTANCE != null) {
return INSTANCE;
}
return new Singleton();
}
}
(TestVolatile.java:55)
at java.lang.Thread.run(Thread.java:748)
19:54:20.432 [monitor] DEBUG juc.visibility.TwoPhaseTerminate - 鏂欑悊鍚庝簨
鍙栨寚浠?- 鎸囦护璇戠爜 - 鎵ц鎸囦护 - 鍐呭瓨璁块棶 - 鏁版嵁鍐欏洖
demo2:
// 鍙互閲嶆帓鐨勪緥瀛?
int a = 10; // 鎸囦护1
int b = 20; // 鎸囦护2
System.out.println( a + b );
// 涓嶈兘閲嶆帓鐨勪緥瀛?
int a = 10; // 鎸囦护1
int b = a - 5; // 鎸囦护2
浜斻€佹湁搴忔€?/h2>
1.鎸囦护閲嶆帓搴忎紭鍖?/h4>
鐜颁唬澶勭悊鍣ㄤ細璁捐涓轰竴涓椂閽熷懆鏈熷畬鎴愪竴鏉℃墽琛屾椂闂存渶闀跨殑 CPU 鎸囦护锛?br> 鎸囦护鍙互鍐嶅垝鍒嗘垚涓€涓釜鏇村皬鐨勯樁娈碉紝渚嬪锛屾瘡鏉℃寚浠ら兘鍙互鍒嗕负锛?br>
3.鍐呭瓨灞忛殰
杩?5 涓樁娈点€?/p>鍦ㄤ笉鏀瑰彉绋嬪簭缁撴灉鐨勫墠鎻愪笅锛岃繖浜涙寚浠ょ殑鍚勪釜闃舵鍙互閫氳繃閲嶆帓搴忓拰缁勫悎鏉ュ疄鐜版寚浠ょ骇骞惰锛岃繖涓€鎶€鏈湪 80's 涓彾鍒?90's 涓彾鍗犳嵁浜嗚绠楁灦鏋勭殑閲嶈鍦颁綅銆?/p>
鎸囦护閲嶆帓鐨勫墠鎻愭槸锛岄噸鎺掓寚浠や笉鑳藉奖鍝嶇粨鏋滐紝渚嬪
2.鏀寔娴佹按绾跨殑澶勭悊鍣?/h4>
鐜颁唬 CPU 鏀寔澶氱骇鎸囦护娴佹按绾匡紝渚嬪鏀寔鍚屾椂鎵ц 鍙栨寚浠?- 鎸囦护璇戠爜 - 鎵ц鎸囦护 - 鍐呭瓨璁块棶 - 鏁版嵁鍐欏洖 鐨勫鐞嗗櫒锛屽氨鍙互绉颁箣涓轰簲绾ф寚浠ゆ祦姘寸嚎銆傝繖鏃?CPU 鍙互鍦ㄤ竴涓椂閽熷懆鏈熷唴锛屽悓鏃惰繍琛屼簲鏉℃寚浠ょ殑涓嶅悓闃舵锛堢浉褰撲簬涓€鏉℃墽琛屾椂闂存渶闀跨殑澶嶆潅鎸囦护锛夛紝IPC = 1锛屾湰璐ㄤ笂锛屾祦姘寸嚎鎶€鏈苟涓嶈兘缂╃煭鍗曟潯鎸囦护鐨勬墽琛屾椂闂达紝浣嗗畠鍙樼浉鍦版彁楂樹簡鎸囦护鍦板悶鍚愮巼銆?/p>
鍏€乿olatile 鍘熺悊
Memory Barrier锛圡emory Fence锛?/p>
鍙鎬?/strong>锛?/p>
鏈夊簭鎬?/strong>: volatile 鐨勫簳灞傚疄鐜板師鐞嗘槸鍐呭瓨灞忛殰锛歁emory Barrier锛圡emory Fence锛?/p>
鍐欏睆闅滐紙sfence锛夛細淇濊瘉鍦ㄨ灞忛殰涔嬪墠鐨勶紝瀵瑰叡浜彉閲忕殑鏀瑰姩锛堜笉鍙槸volatile淇グ鐨勶級锛岄兘鍚屾鍒颁富瀛樺綋涓細 璇诲睆闅滐紙lfence锛夛細淇濊瘉鍦ㄨ灞忛殰涔嬪悗锛屽鍏变韩鍙橀噺鐨勮鍙栵紝鍔犺浇鐨勬槸涓诲瓨涓渶鏂版暟鎹細 鍐欏睆闅滀箣鍓嶇殑閮藉啓杩涗富瀛橈紝璇诲睆闅滀箣鍚庣殑閮戒粠涓诲瓨璇汇€?/p>
鍐欏睆闅滐細纭繚鎸囦护閲嶆帓搴忔椂锛屼笉浼氬皢鍐欏睆闅滀箣鍓嶇殑浠g爜鎺掑湪鍐欏睆闅滀箣鍚?/p>
璇诲睆闅滐細纭繚鎸囦护閲嶆帓搴忔椂锛屼笉浼氬皢璇诲睆闅滀箣鍚庣殑浠g爜鎺掑湪璇诲睆闅滀箣鍓?/p>
涓嶈兘瑙e喅鎸囦护浜ら敊锛?/p>
浠ヤ笂鍗曚緥妯″紡瀛樺湪鐨勯棶棰橈細 鍏朵腑 涔熻 jvm 浼氫紭鍖栦负锛氬厛鎵ц 24锛屽啀鎵ц 21銆傚鏋滀袱涓嚎绋?t1锛宼2 鎸夊涓嬫椂闂村簭鍒楁墽琛岋細 0: getstatic 杩欒浠g爜鍦?monitor 鎺у埗涔嬪锛屽彲浠ヨ秺杩?monitor 璇诲彇INSTANCE 鍙橀噺鐨勫€硷紝杩欐椂 t1 杩樻湭瀹屽叏灏嗘瀯閫犳柟娉曟墽琛屽畬姣曪紝濡傛灉鍦ㄦ瀯閫犳柟娉曚腑瑕佹墽琛屽緢澶氬垵濮嬪寲鎿嶄綔锛岄偅涔?t2 鎷垮埌鐨勬槸灏嗘槸涓€涓湭鍒濆鍖栧畬姣曠殑鍗曚緥銆?/p>
瑙e喅锛?br>
瀵?INSTANCE 浣跨敤 volatile 淇グ鍗冲彲锛屽彲浠ョ鐢ㄦ寚浠ら噸鎺掞紝浣嗚娉ㄦ剰鍦?JDK 5 浠ヤ笂鐨勭増鏈殑 volatile 鎵嶄細鐪熸鏈夋晥锛?/p>
璇诲啓 volatile 鍙橀噺鏃朵細鍔犲叆鍐呭瓨灞忛殰锛圡emory Barrier锛圡emory Fence锛夛級锛屼繚璇佷笅闈袱鐐癸細 鏈夊簭鎬?br>
鍐欏睆闅滀細纭繚鎸囦护閲嶆帓搴忔椂锛屼笉浼氬皢鍐欏睆闅滀箣鍓嶇殑浠g爜鎺掑湪鍐欏睆闅滀箣鍚?br>
璇诲睆闅滀細纭繚鎸囦护閲嶆帓搴忔椂锛屼笉浼氬皢璇诲睆闅滀箣鍚庣殑浠g爜鎺掑湪璇诲睆闅滀箣鍓?/p>
鏇村簳灞傛槸璇诲啓鍙橀噺鏃朵娇鐢?lock 鎸囦护鏉ュ疄鐜板鏍?CPU 涔嬮棿鐨勫彲瑙佹€т笌鏈夊簭鎬?/p>
2.绾跨▼瀵?volatile 鍙橀噺鐨勫啓锛屽鎺ヤ笅鏉ュ叾瀹冪嚎绋嬪璇ュ彉閲忕殑璇诲彲瑙侊細
happens-before 瑙勫畾浜嗗鍏变韩鍙橀噺鐨勫啓鎿嶄綔瀵瑰叾瀹冪嚎绋嬬殑璇绘搷浣滃彲瑙侊紝瀹冩槸鍙鎬т笌鏈夊簭鎬х殑涓€濂楄鍒欐€荤粨 1.绾跨▼瑙i攣 m 涔嬪墠瀵瑰彉閲忕殑鍐欙紝瀵逛簬鎺ヤ笅鏉ュ m 鍔犻攣鐨勫叾瀹冪嚎绋嬪璇ュ彉閲忕殑璇诲彲瑙?/strong>锛?/p>
3.绾跨▼ start 鍓嶅鍙橀噺鐨勫啓锛屽璇ョ嚎绋嬪紑濮嬪悗瀵硅鍙橀噺鐨勮鍙锛?/strong> 5.绾跨▼ t1 鎵撴柇 t2锛坕nterrupt锛夊墠瀵瑰彉閲忕殑鍐欙紝瀵逛簬鍏朵粬绾跨▼寰楃煡 t2 琚墦鏂悗瀵瑰彉閲忕殑璇诲彲瑙侊紙閫氳繃t2.interrupted 鎴?t2.isInterrupted锛?/strong> 6.瀵瑰彉閲忛粯璁ゅ€硷紙0锛宖alse锛宯ull锛夌殑鍐欙紝瀵瑰叾瀹冪嚎绋嬪璇ュ彉閲忕殑璇诲彲瑙?/strong> 7.鍏锋湁浼犻€掓€э紝濡傛灉 x hb-> y 骞朵笖 y hb-> z 閭d箞鏈?x hb-> z 锛岄厤鍚?volatile 鐨勯槻鎸囦护閲嶆帓锛屾湁涓嬮潰鐨勪緥瀛?/strong>
private volatile boolean ready = false;
public void test(Result r) {
//num鏄櫘閫氬彉閲忥紝涔熶細琚悓姝ュ埌涓诲瓨
num = 2;
// ready 鏄?volatile 锛岃祴鍊煎甫鍐欏睆闅?
ready = true;
// 鍐欏睆闅?
}
private volatile boolean ready = false;
public void test(Result r) {
// 璇诲睆闅?
// ready 鏄?volatile 璇诲彇鍊硷紝甯﹁灞忛殰
if(ready) {
r.r1 = num + num;
} else {
r.r1 = 1;
}
}
1.淇濊瘉鍙鎬?/h4>
public void test(Result r) {
num = 2;
// ready 鏄?volatile锛?璧嬪€煎甫鍐欏睆闅?
ready = true;
// 鍐欏睆闅?
}
public void test(Result r) {
// 璇诲睆闅?
// ready 鏄?volatile锛?璇诲彇鍊煎甫璇诲睆闅?
if(ready) {
r.r1 = num + num;
} else {
r.r1 = 1;
}
}
2.淇濊瘉鏈夊簭鎬?/h4>
涓冦€乨ouble-checked lock
public final class Singleton {
private Singleton() { }
private static Singleton INSTANCE = null;
public static Singleton getInstance() {
if(INSTANCE == null) {
synchronized(Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
3.淇濊瘉涓嶄簡鍘熷瓙鎬?/h4>
0: getstatic #2 // Field INSTANCE:Ljuc/visibility/DCLSingleton;
3: ifnonnull 37
6: ldc #3 // class juc/visibility/Singleton
8: dup
9: astore_0
10: monitorenter
11: getstatic #2 // Field INSTANCE:Ljuc/visibility/DCLSingleton;
14: ifnonnull 27
17: new #4 // class juc/visibility/DCLSingleton
20: dup
21: invokespecial #5 // Method "<init>":()V
24: putstatic #2 // Field INSTANCE:Ljuc/visibility/DCLSingleton;
27: aload_0
28: monitorexit
29: goto 37
32: astore_1
33: aload_0
34: monitorexit
35: aload_1
36: athrow
37: getstatic #2 // Field INSTANCE:Ljuc/visibility/DCLSingleton;
40: areturn
Exception table:
getInstance 鏂规硶瀵瑰簲鐨勫瓧鑺傜爜涓?/p>
public class DCLSingleton {
private DCLSingleton() { }
private static volatile DCLSingleton INSTANCE = null;
public static DCLSingleton getInstance() {
if(INSTANCE == null) {
synchronized(Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new DCLSingleton();
}
}
}
return INSTANCE;
}
}
0: getstatic #2 // Field INSTANCE:Ljuc/visibility/DCLSingleton;
3: ifnonnull 37
6: ldc #3 // class juc/visibility/Singleton
8: dup
9: astore_0
10: monitorenter //-----------------------> 淇濊瘉鍘熷瓙鎬с€佸彲瑙佹€?
11: getstatic #2 // Field INSTANCE:Ljuc/visibility/DCLSingleton;
14: ifnonnull 27
17: new #4 // class juc/visibility/DCLSingleton
20: dup
21: invokespecial #5 // Method "<init>":()V
24: putstatic #2 // Field INSTANCE:Ljuc/visibility/DCLSingleton;
// -------------------------------------> 鍔犲叆瀵?INSTANCE 鍙橀噺鐨勫啓灞忛殰
27: aload_0
28: monitorexit //------------------------> 淇濊瘉鍘熷瓙鎬с€佸彲瑙佹€?
29: goto 37
32: astore_1
33: aload_0
34: monitorexit
35: aload_1
36: athrow
37: getstatic #2 // Field INSTANCE:Ljuc/visibility/DCLSingleton;
40: areturn
鍏€乭appens-before
static int x;
static Object m = new Object();
new Thread(() -> {
synchronized (m) {
x = 10;
}
}, "t1").start();
new Thread(() ->{
synchronized (m) {
System.out.println(x);
}
}, "t2").start();
鎶涘紑浠ヤ笅 happens-before 瑙勫垯锛孞MM 骞朵笉鑳戒繚璇佷竴涓嚎绋嬪鍏变韩鍙橀噺鐨勫啓锛屽浜庡叾瀹冪嚎绋嬪璇ュ叡浜彉閲忕殑璇诲彲瑙?/p>
volatile static int x;
new Thread(()->{
x = 10;
},"t1").start();
new Thread(()->{
System.out.println(x);
},"t2").start();
static int x;
x = 10;
new Thread(()->{
System.out.println(x);
},"t2").start();
4.绾跨▼缁撴潫鍓嶅鍙橀噺鐨勫啓锛屽鍏跺畠绾跨▼寰楃煡瀹冪粨鏉熷悗鐨勮鍙锛堟瘮濡傚叾瀹冪嚎绋嬭皟鐢?t1.isAlive() 鎴?t1.join()绛夊緟瀹冪粨鏉燂級
static int x;
Thread t1 = new Thread(()->{
x = 10;
},"t1");
t1.start();
t1.join();
System.out.println(x);
static int x;
public static void main(String[] args) {
Thread t2 = new Thread(()->{
while(true) {
if(Thread.currentThread().isInterrupted()) {
System.out.println(x);
break;
}
}
},"t2");
t2.start();
new Thread(()->{
sleep(1);
x = 10;
t2.interrupt();
},"t1").start();
while(!t2.isInterrupted()) {
Thread.yield();
}
System.out.println(x);
}
volatile static int x;
static int y;
new Thread(()->{
y = 10;
x = 20;
},"t1").start();
new Thread(()->{
// x=20 瀵?t2 鍙, 鍚屾椂 y=10 涔熷 t2 鍙
System.out.println(x);
},"t2").start();