新聞中心
不使用synchronized和lock,如何實(shí)現(xiàn)一個(gè)線程安全的單例?

10年的高坪網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。網(wǎng)絡(luò)營(yíng)銷推廣的優(yōu)勢(shì)是能夠根據(jù)用戶設(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è)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
回答最多的是靜態(tài)內(nèi)部類和枚舉。很好,這兩種確實(shí)可以實(shí)現(xiàn)。
枚舉
- public enum Singleton {
- INSTANCE;
- public void whateverMethod() {
- }
- }
靜態(tài)內(nèi)部類
- public class Singleton {
- private static class SingletonHolder {
- private static final Singleton INSTANCE = new Singleton();
- }
- private Singleton (){}
- public static final Singleton getInstance() {
- return SingletonHolder.INSTANCE;
- }
- }
還有人回答的很簡(jiǎn)單:餓漢。很好,這個(gè)也是對(duì)的。
餓漢
- public class Singleton {
- private static Singleton instance = new Singleton();
- private Singleton (){}
- public static Singleton getInstance() {
- return instance;
- }
- }
餓漢變種
- public class Singleton {
- private static class SingletonHolder {
- private static final Singleton INSTANCE = new Singleton();
- }
- private Singleton (){}
- public static final Singleton getInstance() {
- return SingletonHolder.INSTANCE;
- }
- }
(更多單例實(shí)現(xiàn)方式見(jiàn):?jiǎn)卫J降钠叻N寫法)
問(wèn):這幾種實(shí)現(xiàn)單例的方式的真正的原理是什么呢?
答:以上幾種實(shí)現(xiàn)方式,都是借助了ClassLoader的線程安全機(jī)制。
先解釋清楚為什么說(shuō)都是借助了ClassLoader。
從后往前說(shuō),先說(shuō)兩個(gè)餓漢,其實(shí)都是通過(guò)定義靜態(tài)的成員變量,以保證instance可以在類初始化的時(shí)候被實(shí)例化。那為啥讓instance在類初始化的時(shí)候被實(shí)例化就能保證線程安全了呢?因?yàn)轭惖某跏蓟怯蒀lassLoader完成的,這其實(shí)就是利用了ClassLoader的線程安全機(jī)制啊。
再說(shuō)靜態(tài)內(nèi)部類,這種方式和兩種餓漢方式只有細(xì)微差別,只是做法上稍微優(yōu)雅一點(diǎn)。這種方式是Singleton類被裝載了,instance不一定被初始化。因?yàn)镾ingletonHolder類沒(méi)有被主動(dòng)使用,只有顯示通過(guò)調(diào)用getInstance方法時(shí),才會(huì)顯示裝載SingletonHolder類,從而實(shí)例化instance。。。但是,原理和餓漢一樣。
***說(shuō)枚舉,其實(shí),如果把枚舉類進(jìn)行反序列化,你會(huì)發(fā)現(xiàn)他也是使用了static final來(lái)修飾每一個(gè)枚舉項(xiàng)。(詳情見(jiàn):深度分析Java的枚舉類型—-枚舉的線程安全性及序列化問(wèn)題)
至此,我們說(shuō)清楚了,各位看官的回答都是利用了ClassLoader的線程安全機(jī)制。至于為什么ClassLoader加載類是線程安全的,這里可以先直接回答:ClassLoader的loadClass方法在加載類的時(shí)候使用了synchronized關(guān)鍵字。也正是因?yàn)檫@樣, 除非被重寫,這個(gè)方法默認(rèn)在整個(gè)裝載過(guò)程中都是同步的(線程安全的)。(詳情見(jiàn):深度分析Java的ClassLoader機(jī)制(源碼級(jí)別))
哈哈哈哈!!!~所以呢,這里可以說(shuō),大家的回答都只答對(duì)了一半。雖然沒(méi)有顯示使用synchronized和lock,但是還是間接的用到了!!!!
那么,這里再問(wèn)一句:不使用synchronized和lock,如何實(shí)現(xiàn)一個(gè)線程安全的單例?
【本文是專欄作者Hollis的原創(chuàng)文章,作者微信公眾號(hào)Hollis(ID:hollischuang)】
戳這里,看該作者更多好文
分享文章:不使用synchronized和lock,如何實(shí)現(xiàn)一個(gè)線程安全的單例?
網(wǎng)站鏈接:http://www.dlmjj.cn/article/dhicjje.html


咨詢
建站咨詢
