Java中可怕的雙重檢查鎖定成語

本文討論的問題不是新問題,但即使是經驗豐富的開發人員也仍然很棘手。 單例模式是常見的編程習慣。 但是,當與多個線程一起使用時,必須進行某種類型的同步,以免破壞代碼。

Khangaonkar報告中的 JCG合作伙伴Manoj Khangaonkar在一篇相關文章中詳細研究了雙重檢查的成語,以了解其崩潰之處,并提出了所有可能的解決方案:

免得他說些什么:

Java中的雙重檢查鎖定問題已得到充分證明。 但是,即使是經驗豐富的程序員也可能會過分熱衷于嘗試優化代碼同步,從而創建單例并使其陷入陷阱。

考慮代碼

public class Sample {private static Sample s = null ;public static Sample getSample() {if (s == null) {s = new Sample() ;}return s ;}
}
清單1

此代碼不是線程安全的。 如果2個線程t1和t2同時進入getSample()方法,則它們很可能會獲得不同的樣本實例。 通過將synced關鍵字添加到getSample()方法,可以輕松解決此問題。

public class Sample {private static Sample s = null ;public static synchronized Sample getSample() {if (s == null) {s = new Sample() ;}return s ;}
}
清單2

現在,getSample方法可以正常工作。 在進入getSample方法之前,線程t1獲得一個鎖。 需要進入該方法的任何其他線程t2將阻塞,直到t1退出該方法并釋放鎖為止。 代碼有效。 生活很好。 這是精明的程序員在不謹慎的情況下可以超越自己的地方。 他將注意到,實際上,僅對創建實例的getSample的第一次調用需要進行同步,而僅返回s的后續調用將付出不必要的代價。 他決定優化代碼以

public class Sample {private static Sample s = null ;public static Sample getSample() {if (s == null) {synchronized(Sample.class) {s = new Sample() ;}}return s ;}
}
清單3

我們的Java專家很快意識到該代碼與清單1所存在的問題相同。 因此,他進一步對其進行了微調。

public class Sample {private static Sample s = null ;public static Sample getSample() {if (s == null) {synchronized(Sample.class) {if (s == null) {s = new Sample() ;}}}return s ;}
}
清單4

通過在同步塊中添加額外的檢查,他確保了只有一個線程將創建該示例的實例。 這是雙重檢查模式。 我們的老師的朋友,一位Java專家,好友檢查了該代碼。 簽入代碼并發貨。 生活好嗎?

! 假設線程t1進入getSample。 s為空。 它鎖了。 在同步塊內,它檢查s是否仍然為null,然后執行Sample的構造函數。 在構造函數執行完成之前,將t1換出,并且t2得到控制。 由于構造函數未完成,因此s被部分初始化。 它不為null,但具有一些損壞或不完整的值。 當t2進入getSample時,它將看到s不為null并返回一個損壞的值。

總之,仔細檢查模式不起作用。 選項是在清單2所示的方法級別進行同步,或者放棄同步并使用一個靜態字段,如下所示。

public class Sample {private static Sample INSTANCE = new Sample();public static Sample getSample()  {return INSTANCE ;}
}
清單5

好是好人的敵人!

拜倫

相關文章:

  • Java最佳實踐系列
  • 正確記錄應用程序的10個技巧
  • 每個程序員都應該知道的事情
  • 生存在狂野西部開發過程中的9條提示
  • 軟件設計法則
  • JDK中的設計模式

翻譯自: https://www.javacodegeeks.com/2011/03/dreaded-double-checked-locking-idiom-in.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374920.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374920.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374920.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

國內有哪些好的刷題網站?

http://www.zhihu.com/question/25574458 Luau Lawrence,Data Mining 弱雞 / PhDNTU 溫夢強、石一帆、知乎用戶 等人贊同 - Welcome To PKU JudgeOnline 北京大學的Online Judge。POJ上面的題目有點老了,但好處是做的人多,經典算法題多&…

IE版本判斷

我們常常會在網頁的HTML里面看到形如[if lte IE 9]……[endif]的代碼&#xff0c;表示的是限定某些瀏覽器版本才能執行的語句&#xff0c;那么這些判斷語句的規則是什么呢&#xff1f;請看下文&#xff1a; <!--[if !IE]><!--> 除IE外都可識別 <!--<![endif]…

Js 流程控制

流程控制 順序、分支、循環 順序結構 代碼一行一行從上往下執行并解析 分支結構 if語句 switch語句 if語句 單分支 if(條件表達式){ //語句塊 } 含義&#xff1a;當條件表達式為真的時候就執行里面的語句塊 示例&#xff1a; 雙分支&#xff1a; if(條件表達式){ //語句塊1 }el…

習題6-3 使用函數輸出指定范圍內的完數 (20 分)

本題要求實現一個計算整數因子和的簡單函數&#xff0c;并利用其實現另一個函數&#xff0c;輸出兩正整數m和n&#xff08;0<m≤n≤10000&#xff09;之間的所有完數。所謂完數就是該數恰好等于除自身外的因子之和。例如&#xff1a;6123&#xff0c;其中1、2、3為6的因子。…

速覽Java 7 MethodHandle及其用法

由于Java的Reflection API&#xff0c;我們已經能夠在運行時檢查和更改程序執行。 特別是&#xff0c;我們可以在運行時觀察接口/類/方法和字段&#xff0c;而在編譯時不知道它們的名稱。 JDK 7為這種動態/運行時檢查引入了一個新的參與者&#xff0c;即方法句柄&#xff08;即…

習題6-4 使用函數輸出指定范圍內的Fibonacci數 (20 分)

本題要求實現一個計算Fibonacci數的簡單函數&#xff0c;并利用其實現另一個函數&#xff0c;輸出兩正整數m和n&#xff08;0<m≤n≤10000&#xff09;之間的所有Fibonacci數。所謂Fibonacci數列就是滿足任一項數字是前兩項的和&#xff08;最開始兩項均定義為1&#xff09;…

SmartGWT入門,提供出色的GWT界面

SmartGWT簡介 我最近開始使用SmartGWT &#xff0c;它是一個基于GWT的框架&#xff0c;該框架為您的應用程序UI提供了一個全面的小部件庫&#xff0c;并為服務器端的數據管理提供了幫助。 您可以在SmartGWT展示柜上查看其漂亮的功能。 我準備了一個簡短的“入門”指南&#xf…

Android OpenGL ES(四)----調整屏幕的寬高比

1.寬高比問題 我們現在相當熟悉這樣一個事實&#xff0c;在OpenGL里&#xff0c;我們要渲染的一切物體都要映射到X軸和Y軸上[-1&#xff0c;1]的范圍內&#xff0c;對于Z軸也一樣。這個范圍內的坐標被稱為歸一化設備坐標&#xff0c;其獨立于屏幕實際尺寸或形狀。 不幸的是&…

使用Spring AOP進行面向方面的編程

面向方面的編程&#xff08;AOP&#xff09;是指將輔助功能或支持功能與主程序的業務邏輯隔離開來的編程范例。 AOP是用于分離橫切關注點的有前途的技術&#xff0c;這在面向對象的編程中通常很難做到。 以此方式增加了應用程序的模塊化&#xff0c;并且維護變得非常容易。 橫切…

面試題24 二叉搜索樹的后序遍歷序列

題目描述 輸入一個整數數組&#xff0c;判斷該數組是不是某二叉搜索樹的后序遍歷的結果。如果是則輸出Yes,否則輸出No。假設輸入的數組的任意兩個數字都互不相同。1 class Solution {2 public:3 bool VerifySquenceOfBST(vector<int> sequence) {4 if (seque…

習題6-5 使用函數驗證哥德巴赫猜想 (20 分)

本題要求實現一個判斷素數的簡單函數&#xff0c;并利用該函數驗證哥德巴赫猜想&#xff1a;任何一個不小于6的偶數均可表示為兩個奇素數之和。素數就是只能被1和自身整除的正整數。注意&#xff1a;1不是素數&#xff0c;2是素數。 函數接口定義&#xff1a; int prime( int…

Linux學習筆記 (六)用戶管理命令

一、用戶帳號 1、超級用戶&#xff1a;具有操作系統中的最高權限&#xff0c;用來管理和維護操作系統。root用戶。 2、普通用戶&#xff1a;由root用戶來創建&#xff0c;在宿主目錄中具有完全權限。 3、程序用戶&#xff1a;由應用程序添加&#xff0c;維護某個應用程序運行。…

使用Spring Security保護GWT應用程序

在本教程中&#xff0c;我們將看到如何將GWT與Spring的安全模塊&#xff08;即Spring Security&#xff09;集成在一起。 我們將看到如何保護GWT入口點&#xff0c;如何檢索用戶的憑據以及如何記錄各種身份驗證事件。 此外&#xff0c;我們將實現自定義身份驗證提供程序&#x…

用Fragment制作的Tab頁面產生的UI重疊問題

本文出處&#xff1a;http://blog.csdn.net/twilight041132/article/details/43812745 在用Fragment做Tab頁面&#xff0c;發現有時候進入應用會同時顯示多個Tab內容&#xff0c;UI發生重疊。 當應用被強行關閉后&#xff08;通過手機管家軟件手動強關&#xff0c;或系統為節省…

習題6-6 使用函數輸出一個整數的逆序數 (20 分)

本題要求實現一個求整數的逆序數的簡單函數。 函數接口定義&#xff1a; int reverse( int number );其中函數reverse須返回用戶傳入的整型number的逆序數。 我的代碼&#xff1a; int reverse( int number ) {int n number,res 0,t 0;n (n>0)?n:-n;while(n ! 0){t…

Tomcat 7上具有RESTeasy JAX-RS的RESTful Web服務-Eclipse和Maven項目

開發Web服務的RESTful方法不斷受到越來越多的關注&#xff0c;并且似乎正在將SOAP淘汰。 我不會討論哪種方法更好&#xff0c;但是我相信我們都同意REST更輕量級。 在本教程中&#xff0c;我將向您展示如何使用RESTeasy開發RESTful服務以及如何將它們部署在Tomcat服務器上。 在…

appcmd命令導入導出站點與應用程序池

在IIS7上導出所有應用程序池的方法: %windir%\system32\inetsrv\appcmd list apppool /config /xml > c:\apppools.xml 這個命令會將服務器上全部的應用程序池都導出來,但有些我們是我們不需要的,要將他們刪掉.比如: DefaultAppPoolClassic .Net AppPool如果在導入時發現同名…

卸載apache

1、運行services.msc&#xff0c;在服務中停止 apache 服務。2、運行命令行程序&#xff0c;輸入 sc delete apache&#xff0c;刪除該服務3、刪除apache文件夾。轉載于:https://www.cnblogs.com/jiangjieqim/p/5357950.html

使用wowza和xuggler將RTMP轉換為RTSP

注意&#xff1a;這是我們的“ Xuggler開發教程 ”系列的一部分。 大家好&#xff01; 在過去的三個月中&#xff0c;我們一直在進行電話會議項目。 我們認為&#xff0c;使用諸如Flex之類的技術的基于Web的應用程序將是此類要求苛刻的項目的最佳方法。 隨著軟件的復雜性和電信…

如何設置網頁標題圖標

1、先制作一個名為favicon.ico的小圖標&#xff0c;并將其放到網站根目錄下 2、在html頁面<head></head>標簽內加入&#xff1a; <link rel"shortcut icon" href"favicon.ico" />OK轉載于:https://www.cnblogs.com/moshengr/p/4600281.h…