Parallel.For:锁定值是否安全?

时间:2011-05-18 13:53:23

标签: c# .net parallel-processing

我试图弄清楚这段代码的输出:

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演示。

更新 好吧,我确实发现他们在同一个线程上,但我仍然想知道锁是否阻止执行。我想不到它。

3 个答案:

答案 0 :(得分:2)

如果ID排队,您的lock将仅阻止执行,以便您多次检索相同的请求。由于每次都会打印不同的名称,因此不应该关注。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

Parallel.For使用线程池来处理循环。只要其中一个线程是空闲的,它就会将其分配给下一个元素。这是不确定的,因为您不知道池中有多少个线程,并且您不控制给予每个线程的CPU时间。这意味着某些线程可能会比您“自然”期望的那样早或晚完成。

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