简体   繁体   English

将静态属性作为该类的实例的线程安全考虑因素

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

Please consider this code: 请考虑以下代码:

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);
    }
}

and I want to use this BL in my web page like this: 我想在我的网页中使用这个BL ,如下所示:

BusinessClass.Instance.Update(Item);

My question is: is this code problematic for thread safety? 我的问题是:这个代码对于线程安全是否有问题? Can two people come together at the same time in Update method? Update方法中,两个人可以同时聚在一起吗?

Thanks 谢谢

First case - asp.net session lock 第一种情况 - asp.net会话锁

If you use asp.net forms and the session of asp.net, then the session is lock the entire call for all users, so you don't need to extra take care to synchronize that. 如果您使用asp.net表单和asp.net的会话,那么会话将锁定所有用户的整个调用, 因此您不需要额外注意同步它。

Relative questions : 相关问题:

Does ASP.NET Web Forms prevent a double click submission? ASP.NET Web窗体是否阻止双击提交?
Trying to make Web Method Asynchronous 试图使Web方法异步
Web app blocked while processing another web app on sharing same session 在共享同一会话时处理另一个Web应用程序时阻止了Web应用
What perfmon counters are useful for identifying ASP.NET bottlenecks? 什么perfmon计数器可用于识别ASP.NET瓶颈?
Replacing ASP.Net's session entirely 完全取代ASP.Net的会话

Second case - the local thread. 第二种情况 - 本地线程。

If you not use the asp.net session, or if you open extra threads on the same call , then you need to lock the manipulation of static data. 如果你不使用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);
    }
}

Final case - the global change 最后的案例 - 全球变化

If you wish to double check a global change on the database or on the files, or on anything that can change from simulate edit of the system - on a web platform that runs on web garden (multi pools for the same site)... and ignore the session... 如果您希望在Web园(在同一站点的多个池)上运行的Web平台上仔细检查数据库或文件的全局更改,或者可以从系统的模拟编辑中更改的任何内容...并忽略会话......

Then you need mutex to synchronize all calls. 然后你需要互斥来同步所有的呼叫。

By using mutex , you also need to check just before the update, that the record is still the same and if not you signaling that some one else change it and the current user will overwrite it. 通过使用互斥锁 ,您还需要在更新之前检查,记录仍然是相同的,如果不是,您发信号通知其他人更改它并且当前用户将覆盖它。

More to consider - multi-user environment. 更多考虑因素 - 多用户环境。

Think this scenario. 想想这个场景。
User A and B, load the same page, the same data, and each of one change them. 用户A和B,加载相同的页面,相同的数据,并且每个都更改它们。

the users are going to save each data - not the same moment - but with a lot of time different. 用户将保存每个数据 - 不是同一时刻 - 但是有很多时间不同。 The data that you write down is the last one saved. 您记下的数据是最后保存的数据。 One of the user will lost their changes. 其中一个用户将丢失其更改。

So you need some more to consider and made a lot more synchronization signaling in a multi user environment if your users update the same data - beyond the locking system. 因此,如果您的用户更新相同的数据(锁定系统之外),您还需要更多考虑并在多用户环境中进行更多同步信号传输。

It's not thread-safe. 不是线程安全的。 Here is just one example of what could happen: 以下是可能发生的一个例子:

Thread1: if (myClass == null) <- receives true because it's null Thread1: if (myClass == null) < - 收到true,因为它为null

Thread1: [temp1] = new BusinessClass(); Thread1: [temp1] = new BusinessClass(); <-- [temp1] exists implicitly in Thread 1 < - [temp1]隐含在线程1中

Thread2: if (myClass == null) <- receives true because it's still null Thread2: if (myClass == null) < - 收到true,因为它仍为null

Thread2: [temp2] = new BusinessClass(); Thread2: [temp2] = new BusinessClass(); <-- [temp2] exists implicitly in Thread 2 < - [temp2]隐式存在于线程2中

Thread2: myClass = [temp2]; Thread2: myClass = [temp2];

Thread2: return myClass; Thread2: return myClass; <-- returns second instance created < - 返回创建的第二个实例

Thread1: myClass = [temp1]; Thread1: myClass = [temp1];

Thread1: return myClass; Thread1: return myClass; <-- returns first instance created < - 返回创建的第一个实例

Now each thread holds a different instance of the "singleton" Instance . 现在每个线程都拥有“单例” Instance的不同实例。


An easy-to-use thread-safe direct alternative would be to use a Lazy<BusinessClass> to hold your singleton instance instead of myClass . 一个易于使用的线程安全直接替代方法是使用Lazy<BusinessClass>来保存您的单例实例而不是myClass

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM