C#并发列表问题

标签 c# concurrency

我在 C# 中有一个简单类型列表。这个列表可以被多个线程访问:可以添加或删除条目,可以检查条目是否存在。到目前为止,我已将该列表封装在一个只公开这三个操作的对象中。

我有几个案例要处理(和我刚才说的方法不完全一样)。

  1. 一个线程可以只检查一个条目的存在。 (简单)
  2. 一个线程可以检查一个条目是否存在,如果不存在,则添加它。
  3. 一个线程需要检查一个条目是否存在,如果存在,等待直到它被移除。
  4. 2 和 3 的组合,线程检查条目是否存在,如果它确实存在,它必须等到它被删除,然后才能自己添加它。

整个想法是条目的存在表示锁定。如果条目存在,则无法更改它标识的对象并且代码无法继续,因为它正在别处被修改。

这些可能看起来像是简单的新手情况,但我在并发问题上让自己耳目一新,这让我有点偏执,而且我对 C# 的并发机制也不那么熟悉。

处理此问题的最佳方法是什么?我完全离开了吗?是否应该将检查和添加(测试和设置?)合并为第四个原子操作?我是否会简单地向访问列表的方法添加锁 block ?

另外,是否可以对这种东西进行单元测试(不是简单的操作,并发情况)?

最佳答案

单元测试肯定很难。

这一切都可以通过 .NET 中的“ native ”并发机制合理地简单地完成:锁定语句和 Monitor.Wait/Monitor.PulseAll .除非每个项目都有一个单独的监视器,否则您将需要在删除任何内容时唤醒所有线程 - 否则您将无法告诉“正确的”线程唤醒。

如果它真的只是一组 项,您可能需要使用HashSet<T>而不是 List<T>顺便说一下,代表系列 - 你提到的与订购无关。

示例代码,假设一组适合您:

using System;
using System.Collections.Generic;
using System.Threading;

public class LockCollection<T>
{
    private readonly HashSet<T> items = new HashSet<T>();
    private readonly object padlock = new object();

    public bool Contains(T item)
    {
        lock (padlock)
        {
            return items.Contains(item);
        }
    }

    public bool Add(T item)
    {
        lock (padlock)
        {
            // HashSet<T>.Add does what you want already :)
            // Note that it will return true if the item
            // *was* added (i.e. !Contains(item))
            return items.Add(item);
        }
    }

    public void WaitForNonExistence(T item)
    {
        lock (padlock)
        {
            while (items.Contains(item))
            {
                Monitor.Wait(padlock);
            }
        }
    }

    public void WaitForAndAdd(T item)
    {
        lock (padlock)
        {
            WaitForNonExistence(item);
            items.Add(item);
        }
    }

    public void Remove(T item)
    {
        lock (padlock)
        {
            if (items.Remove(item))
            {
                Monitor.PulseAll(padlock);
            }
        }
    }
}

(诚然,完全未经测试。您可能还想为等待代码指定超时...)

关于C#并发列表问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1075492/

相关文章:

c# - 无论如何将 c# 函数转换为 sql server 存储过程?

c# - 有没有 "single line"方式生成加密字符串?

java - while 循环条件的同步块(synchronized block)

algorithm - 算法应该并行化的一些提示是什么?

java - 简单的Java并发问题

用于按钮单击事件的 C# 代码,ASP.NET

c# - 如何在 .net 中获取可用的 wifi AP 及其信号强度?

c# - 不支持 Linq 表达式

java - JPA 两个事务更新相同的行

java - 按特定顺序运行两个以上线程