C# 在这种情况下,螺纹安全是一个问题?

C# 在这种情况下,螺纹安全是一个问题?,c#,multithreading,concurrency,C#,Multithreading,Concurrency,我是否需要在字典的以下简单getter和setter中使用一些线程安全机制 如果需要,请提供lock和ConcurrentDictionary的示例 public virtual void Add(IFoo foo) { dictionary.Add(foo.name, foo); } public virtual IFoo Get(string name) { if (!dictionary.TryGetValue(na

我是否需要在字典的以下简单getter和setter中使用一些线程安全机制

如果需要,请提供lock和ConcurrentDictionary的示例

    public virtual void Add(IFoo foo)
    {
        dictionary.Add(foo.name, foo);
    }

    public virtual IFoo Get(string name)
    {
        if (!dictionary.TryGetValue(name, out IFoo foo)) return null;
        return foo;
    }

    public virtual bool Has(string name)
    {
        return dictionary.TryGetValue(name, out IFoo foo);
    }

    public virtual IFoo Remove(string name)
    {
        if (dictionary.TryGetValue(name, out IFoo foo))
        {
            dictionary.Remove(name);
        }
        return foo;
    }

    protected readonly IDictionary<string, IFoo> dictionary = new Dictionary<string, IFoo>();
公共虚拟空添加(IFoo-foo)
{
dictionary.Add(foo.name,foo);
}
公共虚拟IFoo Get(字符串名称)
{
if(!dictionary.TryGetValue(name,out-IFoo-foo))返回null;
返回foo;
}
公共虚拟bool Has(字符串名称)
{
返回dictionary.TryGetValue(name,out-IFoo-foo);
}
公共虚拟IFoo删除(字符串名称)
{
if(dictionary.TryGetValue(name,out-IFoo-foo))
{
删除(名称);
}
返回foo;
}
受保护的只读IDictionary dictionary=新字典();

如果您的词典将从不同的线程访问,那么您应该阅读以下关于词典的内容:


只要不修改集合,词典可以同时支持多个读取器。即便如此,通过集合枚举本质上并不是线程安全的过程。在枚举与写访问争用的罕见情况下,必须在整个枚举期间锁定集合。要允许多个线程访问集合进行读写,必须实现自己的同步

我建议使用
ConcurrentDictionary
作为线程安全的集合,它提供原子和线程安全的方法:

所有这些操作都是原子操作,对于ConcurrentDictionary类上的所有其他操作都是线程安全的。唯一的例外是接受委托的方法,即AddOrUpdate和GetOrAdd

检查此链接:

但是,您可以使用
lock
语句,而不是使用自己的锁定代码
要在需要使用
字典的情况下实现线程同步,请检查此链接:

根据要求,这里有一个使用锁的线程安全版本。您的Add方法可以调用
GetOrAdd
AddOrUpdate
,这取决于在争用情况下您希望“第一个赢”还是“最后一个赢”

public virtual void Add(IFoo foo)
{
    AddOrUpdate(foo);   // If you want "last one wins"
    //GetOrAdd(foo);      // If you want "first one wins"
}

private virtual IFoo GetOrAdd(IFoo foo)
{
    lock(dictionary)
    {
        IFoo result;
        if (!dictionary.TryGetValue(foo.name, out result))
        {
            // Not in the dictionary; add it
            result = foo;
            dictionary.Add(foo.name, foo);
        }
        return result;
    }
}
public virtual void AddOrUpdate(IFoo foo)
{
    lock(dictionary)
    {
        // Last one wins and overwrites if there is a race-condition
        dictionary[foo.name] = foo;
    }
}

public virtual IFoo Get(string name)
{
    lock(dictionary)
    {
        IFoo foo;
        dictionary.TryGetValue(name, out foo);
        return foo; // will be null if TryGetValue returned false
    }
}

public virtual bool Has(string name)
{
    lock(dictionary)
    {
        return dictionary.ContainsKey(name);
    }
    // But there's no guarantee it's still there when this method returns
}

public virtual IFoo Remove(string name)
{
    lock (dictionary)
    {
        IFoo result;
        if (dictionary.TryGetValue(name, out result))
        {
            dictionary.Remove(name);
        }
        return result;
    }
}

// Dictionary should be private, not protected to be sure a derived
// class doesn't access it without using locks
private readonly IDictionary<string, IFoo> dictionary = new Dictionary<string, IFoo>();
公共虚拟空添加(IFoo-foo)
{
AddOrUpdate(foo);//如果你想“最后一个赢”
//GetOrAdd(foo);//如果你想“第一个赢”
}
私有虚拟IFoo GetOrAdd(IFoo-foo)
{
锁(字典)
{
IFoo结果;
if(!dictionary.TryGetValue(foo.name,out结果))
{
//不在字典中;添加它
结果=foo;
dictionary.Add(foo.name,foo);
}
返回结果;
}
}
公共虚拟void AddOrUpdate(IFoo-foo)
{
锁(字典)
{
//如果有比赛条件,最后一个获胜并覆盖
字典[foo.name]=foo;
}
}
公共虚拟IFoo Get(字符串名称)
{
锁(字典)
{
伊福福;
TryGetValue(名称,out foo);
return foo;//如果TryGetValue返回false,则将为null
}
}
公共虚拟bool Has(字符串名称)
{
锁(字典)
{
返回dictionary.ContainsKey(名称);
}
//但是不能保证当这个方法返回时它仍然存在
}
公共虚拟IFoo删除(字符串名称)
{
锁(字典)
{
IFoo结果;
if(dictionary.TryGetValue(名称、输出结果))
{
删除(名称);
}
返回结果;
}
}
//字典应该是私有的,不受保护,以确保派生的
//类在不使用锁的情况下不会访问它
专用只读IDictionary dictionary=新字典();
以下是ConcurrentDictionary的版本:

public virtual void Add(IFoo foo)
{
    AddOrUpdate(foo);   // If you want "last one wins"
    //GetOrAdd(foo);      // If you want "first one wins"
}

private virtual IFoo GetOrAdd(IFoo foo)
{
    return concurrentDictionary.GetOrAdd(foo.name, foo);
}
public virtual void AddOrUpdate(IFoo foo)
{
    concurrentDictionary[foo.name] = foo;
}

public virtual IFoo Get(string name)
{
    IFoo result;
    concurrentDictionary.TryGetValue(name, out result);
    return result; // will be null if TryGetValue returned false
}

public virtual bool Has(string name)
{
    return concurrentDictionary.ContainsKey(name);
    // But there's no guarantee it's still there when this method returns
}

public virtual IFoo Remove(string name)
{
    IFoo result;
    concurrentDictionary.TryRemove(name, out result);
    return result;
}

private readonly ConcurrentDictionary<string, IFoo> concurrentDictionary = new ConcurrentDictionary<string, IFoo>();
公共虚拟空添加(IFoo-foo)
{
AddOrUpdate(foo);//如果你想“最后一个赢”
//GetOrAdd(foo);//如果你想“第一个赢”
}
私有虚拟IFoo GetOrAdd(IFoo-foo)
{
返回concurrentDictionary.GetOrAdd(foo.name,foo);
}
公共虚拟void AddOrUpdate(IFoo-foo)
{
concurrentDictionary[foo.name]=foo;
}
公共虚拟IFoo Get(字符串名称)
{
IFoo结果;
concurrentDictionary.TryGetValue(名称、输出结果);
返回结果;//如果TryGetValue返回false,则将为null
}
公共虚拟bool Has(字符串名称)
{
返回concurrentDictionary.ContainsKey(名称);
//但是不能保证当这个方法返回时它仍然存在
}
公共虚拟IFoo删除(字符串名称)
{
IFoo结果;
concurrentDictionary.TryRemove(名称、输出结果);
返回结果;
}
私有只读ConcurrentDictionary ConcurrentDictionary=新的ConcurrentDictionary();

为什么不能使用lock和ConcurrentDictionary编写自己的示例。这个网站不是一个代码编写服务,你需要展示你自己的一些努力,我们可以告诉你你犯了什么错误。我的第一个问题是,在上述情况下,真的需要线程安全吗?请给我一些建议,然后我会编辑这个代码是如何使用的?向我们展示您实际使用的多线程代码。它是一个库,具有添加、删除和函数的单元测试,我不确定如何使用它,但它是否需要线程安全?想象一下,这是一个服务器端应用程序,其中数百万个连接将模拟地访问服务器,该应用程序将使用该库管理所有用户通用的密钥、值对。为所有用户提供一个字典,如果我将其转换为ConcurrentDictionary,我的方法将添加、获取、删除等。对于服务器端的所有用户来说,该字典仍然是线程安全的,它将是所有客户端用户的共享资源“要允许多个线程访问集合进行读写,您必须实现自己的同步。”这也适用于ConcurrentDictionary吗?想象一下,如果上面的字典是ConcurrentDictionary,那么将在每个添加、获取、删除函数中使用lock(this){}?锁定可以与dictionary一起使用,但是