我正在尝试了解学校作业的线程,并且试图获取两个线程以清空集合。到目前为止,我想出的代码抛出了一个异常,说该集合已被修改。
首先,我在锁定的代码部分进行了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就足够了。
可以通过以下方式将其可视化:
等等
关于multithreading - 多线程修改集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10479771/