簡體   English   中英

單例查找表需要鎖嗎?

[英]Lock needed on singleton lookup table?

我下面有一個單身人士。 我有多個線程使用查找來檢查值是否有效。 自從我用共享內存完成任務以來已經有一段時間了,所以我想確保哪些鎖是必要的。 我不確定我是否需要並發集而不是HashSet,因為我只插入一次值。

我在Instance屬性上有[MethodImpl(MethodImplOptions.Synchronized)] ,因為我讀到屬性沒有sycrhonized(有意義)。 這應該可以防止創建多個實例,雖然我不確定我是否真的應該擔心這個問題(只需要重新加載集合的額外成本?)。

我應該使FipsIsValid函數Syncrhonized,還是使用某種並發集? 或者既不必要?

public class FipsLookup
{
    private static FipsLookup instance;

    private HashSet<string> fips;

    private FipsLookup()
    {
        using (HarMoneyDB db = new HarMoneyDB())
        {
            instance.fips = new HashSet<string>(db.Counties.Select(c => c.FIPS).ToArray());
        }
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public static FipsLookup Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new FipsLookup();
            }
            return instance;
        }
    }

    public static bool FipsIsValid(string fips)
    {
        var instance = FipsLookup.Instance;

        return instance.fips.Contains(fips);
    }
}

我應該使FipsIsValid函數Syncrhonized,還是使用某種並發集? 或者既不必要?

我認為這個答案的關鍵是你只在HashSet上執行查找,而不是改變它。 由於它只被初始化一次,並且只有一次,因此不需要同步查找。

如果你確定在確實需要改變它的方式,那么就需要使用正確的lock或並發集合。

在旁注中,您可以通過在靜態構造函數中初始化實例字段來簡化單例:

private static FipsLookup instance;
static FipsLookup() 
{
    instance = new FipsLookup();
}

現在您可以使Instance返回該字段,而無需使用[MethodImpl(MethodImplOptions.Synchronized)]

public static FipsLookup Instance
{
    get
    {
        return instance;
    }
}

這是安全的,因為Instance是同步的,相當於一個鎖。 所有寫入都發生在該鎖定之下。 釋放鎖會刷新所有寫入(釋放屏障)。

此外,所有讀取首先通過鎖定。 無法觀察到部分編寫的hashset。 此答案的先前版本提出以下不正確的聲明:

這不是嚴格安全的(在ECMA下),因為讀者可能會看到半寫的HashSet 在實踐中它是安全的(在Microsoft CLR,因為所有商店都是發布)但我不會使用它,因為沒有理由。

寫這篇文章的時候,我沒注意到MethodImplOptions.Synchronized 因此,為了您的娛樂,這就是您忘記鎖定時會發生的事情。

可能你應該使用Lazy<T>為你處理這個,它給你無鎖讀取。

靜態成員上的MethodImplOptions.Synchronized有點邪惡,因為它鎖定了類的類型對象。 讓我們希望沒有其他人鎖定這個(共享)對象。 我會在代碼審查中失敗,主要是因為沒有理由引入這種代碼味道。

HashSet類不是線程安全的,並且沒有保證你可以從多個線程訪問它,一切都會好的。 我更喜歡使用ConcurrentDictionary。

暫無
暫無

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

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