Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使singleton成员线程安全_C#_Multithreading_Singleton - Fatal编程技术网

C# 如何使singleton成员线程安全

C# 如何使singleton成员线程安全,c#,multithreading,singleton,C#,Multithreading,Singleton,假设我有以下单例: public sealed class singleton { // fields, creation, etc. private static IList<SomeObjectType> _objects = new List<SomeObjectType>(); private ManualResetEvent _updateCompleted = new ManualResetEvent(true); private bool RefreshR

假设我有以下单例:

public sealed class singleton
{
// fields, creation, etc.
private static IList<SomeObjectType> _objects = new List<SomeObjectType>();
private ManualResetEvent _updateCompleted = new ManualResetEvent(true);

private bool RefreshRequired()
{
    //true if records in DB newer than the objects in the list
}

private void RefreshList()
{
    _updateCompleted.Reset();

    //code to refresh the list

    _updateCompleted.Set();
}

public IList<SomeObjectType> Objects
{
    get
    {
        _updateCompleted.Wait();

        if (RefreshRequired())
            RefreshList();

        return _objects;
    }
}

..
公共密封类单例
{
//字段、创建等。
私有静态IList_objects=new List();
private ManualResetEvent\u updateCompleted=新的ManualResetEvent(真);
私有bool RefreshRequired()
{
//如果数据库中的记录比列表中的对象新,则为true
}
私有无效刷新列表()
{
_updateCompleted.Reset();
//刷新列表的代码
_updateCompleted.Set();
}
公共IList对象
{
得到
{
_updateCompleted.Wait();
if(RefreshRequired())
刷新列表();
返回_对象;
}
}
..
通过这种方式,我试图实现存储在列表中的数据在任何客户端读取之前始终是最新的。这种机制非常简单,但迄今为止运行良好。但是,显然,它不足以用于多线程场景。 如果有多个线程访问Objects成员,我只希望第一个线程检查数据是否是最新的,然后在必要时更新列表。在刷新过程中,所有其他线程都应该在检查是否需要刷新之前等待。 我读过很多ablut锁、BlockedCollections和ManualResetEvents,但我不确定该使用哪个概念


你能解释一下你会选择哪一个,以及你将如何解决所描述的任务吗?

我能建议的最佳答案是:

因为如果仅仅发布一个链接,我会被群众大骂,这里有一些从文章中提取的样本供思考。这篇文章主要与性能和适当性有关,所以请阅读这些样本的描述

至于你的刷新方法,其他人对此评论得相当好。知道如何使用它同样重要

希望这篇文章能给你一些思考的食物

简单线程安全

public sealed class Singleton
{
    private static Singleton instance = null;
    private static readonly object padlock = new object();

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
}
线程安全,无需使用锁

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}
完全惰性实例化

public sealed class Singleton
{
    private Singleton()
    {
    }

    public static Singleton Instance { get { return Nested.instance; } }

    private class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}
使用.NET4的惰性类型

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy =
        new Lazy<Singleton>(() => new Singleton());

    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
}
公共密封类单例
{
私有静态只读惰性=
新的懒惰(()=>newsingleton());
公共静态单例实例{get{return lazy.Value;}}
私人单身人士()
{
}
}

objects变量不需要任何帮助,因为它是由静态构造函数创建的。没有简单的方法使objects属性线程安全,您不知道客户机代码何时停止使用返回值。只有客户机代码可以正确执行。将作业传递给最不可能正确执行的程序员是编写线程安全代码如此困难的一个核心原因是,“线程安全”的整个概念本身。您的第一步是弄清楚您真正的意思。“始终保持最新”同样也很模糊;总会有竞争条件……在这种情况下,你需要决定你想要什么样的行为。如果在“第一个”时有新的数据可用怎么办是否正在更新列表?其他线程应该看到什么?这只是表面现象……您还有很多工作要做。好吧,也许“线程安全”这个术语太多(或错误)为了我真正想要的。在阅读了链接文章之后,Peter,我想说我只想在刷新列表时阻止其他线程。我还试图弄明白,Hans,你说的“只有客户端代码才能正确执行”是什么意思,但我不明白。是不是,可能有一个线程使用返回值当另一个发现列表不是最新的时?您不是在寻找ThreadSave Singleton。您想使用ThreadSave集合(Singleton是一个类的单个实例,它提供的信息比集合多)。您正在寻找类似。也可能(如果您想继续使用您的设计),如果你感兴趣的话,你可以做简单的锁定并打包对你收藏的每一次访问。我发布了一个例子。这并不能解决问题中描述的问题。Servy是对的,但感谢你的努力,Atoms。我确实知道单例模式及其实现,因此,上面没有提到它。如果第一个线程进入和其他线程进入之间的时间跨度足够大,ManualResetEvent应该可以执行,但是如果有线程几乎同时进入,这个机制只是在减速——至少在我看来是这样。