gpt4 book ai didi

c# - 当必须锁定每个列表元素时,多个线程应该如何访问列表?

转载 作者:行者123 更新时间:2023-11-30 16:09:20 25 4
gpt4 key购买 nike

我有一个“模块”类列表,List<Module> modules .这些模块每个都包含自己的公共(public)对象,在访问数据时用作锁。假设我有几个线程在随机时间对这些模块执行处理。目前我让每个线程按顺序对模块执行处理,如下所示:

foreach (Module module in modules)
{
lock (module.Locker)
{
//Do stuff
}
}

到目前为止一切正常,但我感觉有很多不必要的等待。例如,如果两个线程一个接一个地启动,但第一个正在执行繁重的处理而第二个不是,则第二个线程将不得不在第一个线程执行其处理时等待每个模块。

这就是问题所在:是否有一种“正确”或“最有效”的方式来锁定列表中的元素?我打算这样做:

foreach (Module module in modules.Randomize())
{
lock (module.Locker)
{
//Do stuff
}
}

其中“Randomize()”只是一个扩展方法,它以随机顺序返回列表的元素。但是,我想知道是否有比随机更好的方法?

最佳答案

假设锁内的工作量巨大且竞争激烈。我引入了创建新 List<T> 的额外开销并从中删除项目。

public void ProcessModules(List<Module> modules)
{
List<Module> myModules = new List<Module>(modules);//Take a copy of the list
int index = myModules.Count - 1;
while (myModules.Count > 0)
{
if (index < 0)
{
index = myModules.Count - 1;
}

Module module = myModules[index];
if (!Monitor.TryEnter(module.Locker))
{
index--;
continue;
}

try
{
//Do processing module
}
finally
{
Monitor.Exit(module.Locker);
myModules.RemoveAt(index);
index--;
}
}
}

此方法所做的是获取传入模块的副本,然后尝试获取锁,如果无法获取锁(因为另一个线程拥有它),它会跳过并继续前进。完成列表后,它再次查看是否有另一个线程释放了锁,如果没有再次跳过它并继续前进。这个循环一直持续到我们处理完列表中的所有模块。

这样,我们就不会等待任何争用的锁,我们只会继续处理未被另一个线程锁定的模块。

关于c# - 当必须锁定每个列表元素时,多个线程应该如何访问列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27795200/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com