摘要:基礎系列的與方法類初始化順序線程池如何彈性伸縮的幾個要點的緩存什么場景下使用阻塞隊列的使用及模式中的序本文主要介紹的相關知識。典型的使用場景,作為,采用來做信號通知不采用的容易出錯即模式,就是雙加鎖檢查模式。因而有了雙重檢測模式的應用。
Java基礎系列
Java的hashcode與equals方法
Java類初始化順序
ThreadPoolExecutor線程池如何彈性伸縮
HashMap的幾個要點
Integer的緩存
什么場景下使用阻塞隊列
volatile的使用及DCL模式
try-catch-finally中的return
序本文主要介紹volatile的相關知識。
volatile要點volatile 只保證變量的線程可見性,不保證變量的原子性(只對賦值起作用),另外一個作用是防止重排序。
volatile 典型的使用場景,作為boolean,采用while來做信號通知
不采用volatile的dcl容易出錯(DCL即Double Check Locking模式,就是雙加鎖檢查模式。)
代碼實例單例的延遲加載實現
package cn.javass.dp.singleton.example2; /** * 懶漢式單例示例 */ public class Singleton { /** * 定義一個變量來存儲創(chuàng)建好的類實例 */ private static Singleton uniqueInstance = null; /** * 私有化構造方法,好在內部控制創(chuàng)建實例的數目 */ private Singleton(){ // } /** * 定義一個方法來為客戶端提供類實例 * @return 一個Singleton的實例 */ public static synchronized Singleton getInstance(){ //判斷存儲實例的變量是否有值 if(uniqueInstance == null){ //如果沒有,就創(chuàng)建一個類實例,并把值賦值給存儲類實例的變量 uniqueInstance = new Singleton(); } //如果有值,那就直接使用 return uniqueInstance; } }
上面的代碼雖然在多線程的情況是線程安全的,也確保了只有一個實例,但是在高并發(fā)的情況下,synchronized 關鍵字會使得性能下降。
因此,不用synchronized修飾此方法,改在保證實例化實例的時候只有一個線程執(zhí)行就可以了。因而有了雙重檢測模式的應用。
假設線程A,B同時進入該方法,都檢測到instance為null,然后假設A先占用了同步鎖,然后實例化對象,之后B也會占用同步鎖去實例化,因而這里需要再一次檢測實例時是否已經被創(chuàng)建了,此為雙重檢測的來源。
package cn.javass.dp.singleton.example10; public class Singleton { /** * 對保存實例的變量添加volatile的修飾 */ private volatile static Singleton instance = null; private Singleton(){ } public static Singleton getInstance(){ //先檢查實例是否存在,如果不存在才進入下面的同步塊 if(instance == null){ //同步塊,線程安全的創(chuàng)建實例 synchronized(Singleton.class){ //再次檢查實例是否存在,如果不存在才真的創(chuàng)建實例 if(instance == null){ instance = new Singleton(); } } } return instance; } }為什么使用volatile關鍵字 1、volatile能夠保證變量在多線程之間的可見性
即 JVM的volatile語義保證了一個線程更新了這個變量,其他線程再下次讀取的時候,回去刷新本地緩存
2、為什么在JDK5之前是不安全的在JDK5之前,java的內存模型允許out-of-writer,具體如下:
(1)java的new不是原子的,具體在更細的層面還是有諸多步驟:
A、 分配新對象的內存
B、調用類的構造器,初始化成員字段
C、 instance被賦為指向新的對象的引用。
說白了,JDK5之前不能保證有volatile修飾的對象構造內部是有序的。
(2)線程A發(fā)現instance沒有被實例化,它獲得鎖,然后去實例化該對象,JVM容許在沒有完全實例化完成的時候,將實例的指針賦給這個instance變量,而此時instance==null就為false了,在初始化完成之前,線程B進入此方法,發(fā)現instance不為空,認為已經初始化完成了,于是便使用了這個尚未完全初始化的實例對象,可能引起其他的異常。
64位long和double在JVM規(guī)范中Java內存模型要求lock、unlock、read、load、assign、use、store、write這8個操作必須是原子的,但是對于64位的long和double來說,如果沒有被volatile修飾符修飾,那么可以不是原子的,注意是可以,即虛擬機在實現的時候可以選擇是否是原子操作。目前幾乎所有的商用虛擬機都將此實現為原子操作,因此不必每次用到它們都去加volatile修飾。
參考JVM并發(fā)機制的探討——內存模型、內存可見性和指令重排序
關于Java中的volatile型變量
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/65581.html
摘要:單例模式概述單例模式是一種對象創(chuàng)建模式,用于產生一個類的具體事例。所以解決了線程安全問題參考失效原因和解決方案中單例模式的缺陷及單例的正確寫法懶漢式靜態(tài)內部類私有構造器獲取單例的方法靜態(tài)內部類持有單例作為靜態(tài)屬性。 單例模式概述 單例模式是一種對象創(chuàng)建模式,用于產生一個類的具體事例。使用單例模式可以確保整個系統中單例類只產生一個實例。有下面兩大好處: 對于頻繁創(chuàng)建的對象,節(jié)省初第一...
摘要:雙重檢查鎖定以下稱為已被廣泛當做多線程環(huán)境下延遲初始化的一種高效手段。由于沒有對這些做出明確規(guī)定,很難說是否有效。可以在中使用顯式的內存屏障來使生效,但中并沒有這些屏障。如果改變鎖釋放的語義釋放時執(zhí)行一個雙向的內存屏障將會帶來性能損失。 雙重檢查鎖定(以下稱為DCL)已被廣泛當做多線程環(huán)境下延遲初始化的一種高效手段。 showImg(http://segmentfault.com/i...
摘要:面試官要不你來手寫下單例模式唄候選者單例模式一般會有好幾種寫法候選者餓漢式簡單懶漢式在方法聲明時加鎖雙重檢驗加鎖進階懶漢式靜態(tài)內部類優(yōu)雅懶漢式枚舉候選者所謂餓漢式指的就是還沒被用到,就直接初始化了對象。面試官:我看你的簡歷寫著熟悉常見的設計模式,要不你來簡單聊聊你熟悉哪幾個吧?候選者:常見的工廠模式、代理模式、模板方法模式、責任鏈模式、單例模式、包裝設計模式、策略模式等都是有所了解的候選者:...
摘要:總結單例是運用頻率很高的模式,因為客戶端沒有高并發(fā)的情況,選擇哪種方式并不會有太大的影響,出于效率考慮,推薦使用和靜態(tài)內部類實現單例模式。 單例模式介紹 單例模式是應用最廣的模式之一,也可能是很多人唯一會使用的設計模式。在應用單例模式時,單例對象的類必須保證只用一個實例存在。許多時候整個系統只需要一個全局對象,這樣有利于我么能協調整個系統整體的行為。 單例模式的使用場景 確保某個類有且...
閱讀 3500·2023-04-26 02:40
閱讀 4870·2021-09-22 15:22
閱讀 1994·2021-09-22 10:02
閱讀 3685·2021-08-11 10:23
閱讀 1525·2019-08-30 15:55
閱讀 2628·2019-08-30 12:48
閱讀 757·2019-08-30 11:04
閱讀 846·2019-08-29 16:29