簡體   English   中英

將靜態屬性作為該類的實例的線程安全考慮因素

[英]Thread safety consideration for static property as an Instance of that class

請考慮以下代碼:

public class BusinessClass
{
    static BusinessClass myClass { get; set; }
    Repository repo;

    public BusinessClass()
    {
        if (repo == null)
            repo = new RepositoryClass();
    }

    public static BusinessClass Instance
    {
        get
        {
            if (myClass == null)
                myClass = new BusinessClass();
            return myClass ;
        }
    }

    public void Update(Entity Item)
    {
        repo.Update(Item);
    }
}

我想在我的網頁中使用這個BL ,如下所示:

BusinessClass.Instance.Update(Item);

我的問題是:這個代碼對於線程安全是否有問題? Update方法中,兩個人可以同時聚在一起嗎?

謝謝

第一種情況 - asp.net會話鎖

如果您使用asp.net表單和asp.net的會話,那么會話將鎖定所有用戶的整個調用, 因此您不需要額外注意同步它。

相關問題:

ASP.NET Web窗體是否阻止雙擊提交?
試圖使Web方法異步
在共享同一會話時處理另一個Web應用程序時阻止了Web應用
什么perfmon計數器可用於識別ASP.NET瓶頸?
完全取代ASP.Net的會話

第二種情況 - 本地線程。

如果你不使用asp.net會話,或者你在同一個調用上打開額外的線程 ,那么你需要鎖定靜態數據的操作。

public class BusinessClass
{
    private static readonly object oLock = new object();

    static BusinessClass myClass { get; set; } = null;
    Repository repo;

    public BusinessClass()
    {
        if (repo == null)
            repo = new RepositoryClass();
    }

    public static BusinessClass Instance
    {
        get
        {
            if myClass == null)
            {
                lock (oLock)
                {
                    if myClass == null)
                        myClass = new BusinessClass();
                }
            }
            return myClass  
        }
    }

    public void Update(Entity Item)
    {
        repo.Update(Item);
    }
}

最后的案例 - 全球變化

如果您希望在Web園(在同一站點的多個池)上運行的Web平台上仔細檢查數據庫或文件的全局更改,或者可以從系統的模擬編輯中更改的任何內容...並忽略會話......

然后你需要互斥來同步所有的呼叫。

通過使用互斥鎖 ,您還需要在更新之前檢查,記錄仍然是相同的,如果不是,您發信號通知其他人更改它並且當前用戶將覆蓋它。

更多考慮因素 - 多用戶環境。

想想這個場景。
用戶A和B,加載相同的頁面,相同的數據,並且每個都更改它們。

用戶將保存每個數據 - 不是同一時刻 - 但是有很多時間不同。 您記下的數據是最后保存的數據。 其中一個用戶將丟失其更改。

因此,如果您的用戶更新相同的數據(鎖定系統之外),您還需要更多考慮並在多用戶環境中進行更多同步信號傳輸。

不是線程安全的。 以下是可能發生的一個例子:

Thread1: if (myClass == null) < - 收到true,因為它為null

Thread1: [temp1] = new BusinessClass(); < - [temp1]隱含在線程1中

Thread2: if (myClass == null) < - 收到true,因為它仍為null

Thread2: [temp2] = new BusinessClass(); < - [temp2]隱式存在於線程2中

Thread2: myClass = [temp2];

Thread2: return myClass; < - 返回創建的第二個實例

Thread1: myClass = [temp1];

Thread1: return myClass; < - 返回創建的第一個實例

現在每個線程都擁有“單例” Instance的不同實例。


一個易於使用的線程安全直接替代方法是使用Lazy<BusinessClass>來保存您的單例實例而不是myClass

暫無
暫無

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

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