multithreading - 多线程修改集合

标签 multithreading c#-4.0

我正在尝试了解学校作业的线程,并且试图获取两个线程以清空集合。到目前为止,我想出的代码抛出了一个异常,说该集合已被修改。

首先,我在锁定的代码部分进行了while循环,但是(当然; ;-))只有一个线程清空了集合。

我的问题是,我怎样才能有一个循环,使两个线程轮流清空集合?

class Program
{
    private static List<int> containers = new List<int>();

    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            containers.Add(i);
        }

        Thread t1 = new Thread(() => { foreach (int container in containers) { GeefContainer(); } });
        t1.Name = "Kraan 1";
        t1.Start();

        Thread t2 = new Thread(() => { foreach (int container in containers) { GeefContainer(); } });
        t2.Name = "Kraan 2";
        t2.Start();

        Console.Write("Press any key to continue...");
        Console.Read();
    }

    static void GeefContainer()
    {
        lock (containers)
        {
            int containerNummer = containers.Count - 1;

            //Container container = containers[containerNummer];

            //Console.Write("Container {0} opgehaald... Overladen", containerNummer);
            Console.WriteLine("Schip: Container {0} gegeven aan {1}", containerNummer, Thread.CurrentThread.Name);

            //Gevaarlijk, want methode aanroepen kan klappen
            containers.RemoveAt(containerNummer);
        }
    }
}

最佳答案

我假设您不允许使用System.Collections.Concurrent命名空间中找到的任何ThreadSafe集合。

检查是否还有剩余条目时,需要获得对容器集合的独占访问权。但是,您不希望1个线程在释放其锁之前采取排他控制权删除所有条目。 Monitor.Pulse可用于允许其他等待锁定容器的线程“先行”。尝试以下GeefContainers实现:

static void GeefContainer()
{
    lock (containers)
    {
        while (containers.Any()) // using linq, similar to: while(container.Count > 0)
        {
            containers.RemoveAt(0); // remove the first element

            // allow other threads to take control
            Monitor.Pulse(containers); // http://msdn.microsoft.com/en-us/library/system.threading.monitor.pulse.aspx
                            // Wait for a pulse from the other thread
                            Monitor.Wait(container);
        }
    }
}

哦,从以下位置删除循环逻辑:
Thread t2 = new Thread(() => { foreach (int container in containers) { GeefContainer(); } });

只需调用GeefContainer就足够了。

可以通过以下方式将其可视化:
  • 线程1锁定了“collections”
  • 线程2被阻止,因为它正在等待对“集合”的独占锁定
  • 线程1从“集合”中删除条目
  • 线程1释放对“收藏夹”的锁定,并尝试获得新的独占锁定
  • 线程2获得了对“收藏集”
  • 的锁定
  • 线程2从“收藏夹”
  • 中删除了一个条目
  • 线程2释放对“收藏夹”的锁定,并尝试获得新的独占锁定
  • 线程1获得了对“collections”
  • 的锁定

    等等

    关于multithreading - 多线程修改集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10479771/

    相关文章:

    java - 学习多线程Java爬虫的好起点

    java - 在Java中,有没有办法在通知线程后获取线程的实际等待时间

    java - 如何在java中加入一个线程与另一个线程?

    python - 为什么这种递归不会超出递归限制

    java - Java 中的并发 HTTP URL 连接

    c#-4.0 - 如何在单个条件下为实体上的今天日期和两个日期属性编写 "Between"查询表达式?

    entity-framework - 带有 SQL Server Express 迁移异常的 Entity Framework 4.3

    c# - 错误的使用?运算符[重复项]

    c# - 为什么要升级到 c# 4.0?

    linq-to-sql - 带有泛型的 Linq Where 子句无法识别 Equals 基类型