簡體   English   中英

以下getInstance()方法有什么問題

[英]What's wrong with the following getInstance() method

我一直在學習求職面試,但發現了以下問題:

以下Singleton工廠方法getInstance()有什么問題?

public class Singleton {

    private static Singleton mySingleton;

    protected Singleton() {}

    public static Singleton getInstance() {
        if (mySingleton == null) {
           synchronized(Singleton.class) {
             if(mySingleton == null) {
                mySingleton = new Singleton();
             }
           }
        }
        return mySingleton
    }   
}

我知道構造函數是錯誤的,應該是私有的。 但是,他們在問getInstance()方法有什么問題,對我來說一切都很好,我已經看到了很多這樣的示例(在多線程環境中),我還缺少什么?

原始代碼的最大問題是,它是Double Check反模式的經典示例。 看起來不錯,但剛剛壞了。 此處的更多信息: http : //www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

請注意,從Java 1.5開始,有一種完善的方法,同步模式或更好的靜態初始化才是真正的方法。

-edit(我剛剛注意到這是在學習求職面試。如果他們顯示此示例,請抽出“仔細檢查”會很好。如果要求提供詳細信息,我將處理一些您不太了解但可以接受的復雜Java內存問題避免再次檢查的事實。祝您好運)

這看起來確實是線程安全的,但是代碼比需要的復雜。 加上使用鎖,會帶來性能成本。 獲取鎖需要花費時間,並且其他試圖執行該代碼的線程也會被阻塞。

這兩個問題可以通過使用靜態初始化程序並從getInstance方法中完全刪除同步來解決。 JVM將確保該語句僅執行一次。 結果是大大簡化了代碼,而使性能略有提高。

public class Singleton {

    private static Singleton mySingleton = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return mySingleton;
    }   
}

我想念什么?

JLS 17中描述了可能的內存影響,因此對mySingleton的寫入和讀取之間沒有任何先發生后關系。 這是違反直覺的,但是如果您檢查mySingleton不為null,則會看到錯誤的對象。 即在此示例中,mySingleton可以同時讀寫,這稱為數據爭用。 要修復此程序,您只需添加volatile。 根據規范,它在寫入和讀取之間創建事前關聯。

你不是有點多余嗎? 怎么樣呢?

public static synchronized Singleton getInstance()
    {
        if (mySingleton == null)
            mySingleton = new Singleton();

        return mySingleton;
    }

要么...

public static synchronized Singleton getInstance()
    {
        return mySingleton==null?mySingleton=new Singleton():mySingleton;
    }

贊揚Polywhirl先生

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM