Parallel.For:锁定值是否安全

本文关键字:是否 安全 锁定 For Parallel | 更新日期: 2023-09-27 17:57:05

我试图找出这段代码的输出:

Dictionary<int, MyRequest> request = new Dictionary<int, MyRequest>();
for (int i = 0; i < 1000; i++ )
{
  request.Add(i, new MyRequest() { Name = i.ToString() });
}
var ids = request.Keys.ToList();
Parallel.For(0, ids.Count, (t) =>
{
  var id = ids[t];
  var b = request[id];
  lock (b)
  {
    if (b.Name == 4.ToString())
    {
      Thread.Sleep(10000);
    }
    Console.WriteLine(b.Name);
  }
});
Console.WriteLine("done");
Console.Read();

输出:

789
800
875
.
.
.
4
5
6
7
done

MyRequest 只是一个用于演示的虚拟类(它除了保存值之外什么都不做)。 我的锁是阻止执行还是最后 4 个被放在自己的线程上?

这是一个 .NET 4.0 演示。

更新好的,我确实发现它们在同一个线程上,但我仍然想知道锁是否阻止执行。 我无法想象它会。

Parallel.For:锁定值是否安全

如果ids不包含重复项,则该锁不会阻止任何内容。但是,如果 ids 中有重复项,那么是的,锁上可能存在争用,因为不同的线程争夺对同一请求的访问。

只有当 id 排列成一条形

,以便您多次检索同一请求时,您的lock才会阻止执行。由于每次打印不同的名称,因此这不应该是一个问题。

Parallel.For使用线程池来处理循环。一旦它的一个线程是空闲的,它就会将其分配给下一个元素。这是不确定的,因为您不知道池中有多少线程,并且无法控制为每个线程提供的 CPU 时间。这意味着某些线程可能比您"自然"预期的迟早完成。

您的锁没有执行任何操作。锁块分隔尝试使用同一对象的代码段。在您的情况下,您不会在循环中两次使用同一个对象。最后处理的 ID 似乎一致这一事实可能纯粹是巧合。