真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

java雙重檢查鎖問(wèn)題怎么解決

這篇文章主要講解了“java雙重檢查鎖問(wèn)題怎么解決”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“java雙重檢查鎖問(wèn)題怎么解決”吧!

10余年的含山網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。全網(wǎng)整合營(yíng)銷(xiāo)推廣的優(yōu)勢(shì)是能夠根據(jù)用戶(hù)設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整含山建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。成都創(chuàng)新互聯(lián)公司從事“含山網(wǎng)站設(shè)計(jì)”,“含山網(wǎng)站推廣”以來(lái),每個(gè)客戶(hù)項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

雙重檢查鎖由來(lái)

首先我們來(lái)看一下非線程安全的初始化單例模式

	public class UnsafeLazyInitialization {
		private static UnsafeLazyInitialization instance;

		public static UnsafeLazyInitialization getInstance(){
			if(instance == null){                           //1:  線程A執(zhí)行
				instance = new UnsafeLazyInitialization();  //2: 線程B執(zhí)行
			}
			return instance;
		}
	}

在 UnsafeLazyInitialization 類(lèi)中,假設(shè)線程A執(zhí)行到代碼1的時(shí)候,線程B執(zhí)行到代碼2, 這時(shí)候線程A 可能 看到 instance 引用對(duì)象還沒(méi)有完成初始化。

對(duì)于 UnsafeLazyInitialization 類(lèi),我們可以對(duì)getInstance()方法做同步處理來(lái)實(shí)現(xiàn)來(lái)實(shí)現(xiàn)線程安全的延遲初始化,示例代碼如下:

	public static synchronized  UnsafeLazyInitialization getInstance(){
			if(instance == null){                           //1:  線程A執(zhí)行
				instance = new UnsafeLazyInitialization();  //2: 線程B執(zhí)行
			}
			return instance;
		}
	}

由于上述代碼對(duì)getInstance()方法做了同步處理,這樣可能導(dǎo)致同步程序開(kāi)銷(xiāo)加大。 如果getInstance()被多個(gè)線程頻繁調(diào)用,將會(huì)導(dǎo)致程序執(zhí)行性能降低,反之如果不是被多個(gè)線程調(diào)用,那個(gè)這個(gè)getInstance()方法的延遲初始化方法將影響性能。

JVM 1.6之前 synchronized是重量級(jí)鎖,所以很耗費(fèi)性能,所以人們想到了一個(gè)種雙重校驗(yàn)鎖(Dobule-check Locking)的方案來(lái)提高性能,示例代碼如下:

	public class DoubleCheckedLocking {                                 //1、
		private static Instance instance;                               //2、
		public static Instance getInstance(){                          //3、
			if(instance == null){                                      //4、第一次檢查
				synchronized (DoubleCheckedLocking.class){              //5、枷鎖
					if(instance == null){                                //6、第二次檢查
						instance = new Instance();                       //7、問(wèn)題的根源在這里
					}                                                    //8、
				}
			}
			return instance;
		}
	}

如上代碼所示:如果 步驟4、第一次檢查instance不為null,則就不需要執(zhí)行下面的加鎖操作,大大降低了synchronized 鎖帶來(lái)的性能問(wèn)題。上面代碼看起來(lái)沒(méi)有任何問(wèn)題。 1、多個(gè)線程視圖去創(chuàng)建新對(duì)象的時(shí)候,通過(guò)synchronized關(guān)鍵字可以保證只有一個(gè)線程創(chuàng)建對(duì)象成功。

2、如果instance 實(shí)例對(duì)象已經(jīng)被創(chuàng)建,則直接通過(guò)getInstatnce()方法獲取對(duì)象實(shí)例。

上面雙重校驗(yàn)鎖問(wèn)題

上面代碼看上去很完美,但是當(dāng)執(zhí)行步驟4的時(shí)候,instatnce!=null 的時(shí)候,instatnce 的引用對(duì)象有可能還沒(méi)有完成初始化。

問(wèn)題的根源

上面代碼我們執(zhí)行到步驟7的時(shí)候,instance = new Instance(); ,創(chuàng)建了一個(gè)對(duì)象,這個(gè)創(chuàng)建對(duì)象的步驟可以分為三步,如下:

	memory = allocate()  //1.分配內(nèi)存空間memory
	ctorInstance(memory) //2, 初始化對(duì)象在內(nèi)存 分配內(nèi)存空間memory上初始化 Singleton 對(duì)象
	instance = memory //3、設(shè)置 instance 指向剛分配的內(nèi)存地址memory

上面三行代碼 2和3可能發(fā)生重排序,在(JTI編譯器上,這種重排序是真是發(fā)生的) 步驟2和步驟3發(fā)生重排序后執(zhí)行順序

	memory = allocate()  //1.分配內(nèi)存空間memory
	instance = memory //3、設(shè)置 instance 指向剛分配的內(nèi)存地址memory
									// 注意此時(shí)instance對(duì)象還沒(méi)有被初始化,但是instance的引用已經(jīng)不是null了。
	ctorInstance(memory) //2, 初始化對(duì)象在內(nèi)存 分配內(nèi)存空間memory上初始化 Singleton 對(duì)象

下面看一下多線程執(zhí)行順序

java雙重檢查鎖問(wèn)題怎么解決

java雙重檢查鎖問(wèn)題怎么解決

上述代碼第7行instance = new Instance(); 如果A線程發(fā)生指令重排序(2,3),那么另一個(gè)線程B有可能在4行代碼判斷 instance 不為空。線程B接下來(lái)訪問(wèn)instance的引用對(duì)象,但是instance對(duì)象有可能還沒(méi)被A初始化完成。此時(shí)線程B可能訪問(wèn)一個(gè)沒(méi)有初始化完成的對(duì)象,導(dǎo)致報(bào)空指針錯(cuò)誤。

問(wèn)題解決

1、不允許2、3進(jìn)行指令重排。 2、允許2、3進(jìn)行重排序,但是不允許其它線程看到重排序

基于volatile 的解決方案

基于上面代碼只需要在instance聲明時(shí)加上volatile關(guān)鍵字就可以,如下代碼

	public class DoubleCheckedLocking {                                 //1、
		private static volatile Instance instance;                               //2、
		public static Instance getInstance(){                          //3、
			if(instance == null){                                      //4、第一次檢查
				synchronized (DoubleCheckedLocking.class){              //5、枷鎖
					if(instance == null){                                //6、第二次檢查
						instance = new Instance();                       //7、問(wèn)題的根源在這里
					}                                                    //8、
				}
			}
			return instance;
		}
	}

感謝各位的閱讀,以上就是“java雙重檢查鎖問(wèn)題怎么解決”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)java雙重檢查鎖問(wèn)題怎么解決這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!


文章標(biāo)題:java雙重檢查鎖問(wèn)題怎么解決
標(biāo)題網(wǎng)址:http://weahome.cn/article/jedjoe.html

其他資訊

在線咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部