我试图弄清楚这段代码的输出:
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演示。
更新 好吧,我确实发现他们在同一个线程上,但我仍然想知道锁是否阻止执行。我想不到它。
答案 0 :(得分:2)
如果ID排队,您的lock
将仅阻止执行,以便您多次检索相同的请求。由于每次都会打印不同的名称,因此不应该关注。
答案 1 :(得分:2)
如果ids
不包含重复项,则该锁定不会阻止任何内容。但是如果ids
中存在重复项,那么是的,锁可能存在争用,因为不同的线程争夺对同一请求的访问权。
答案 2 :(得分:1)
Parallel.For
使用线程池来处理循环。只要其中一个线程是空闲的,它就会将其分配给下一个元素。这是不确定的,因为您不知道池中有多少个线程,并且您不控制给予每个线程的CPU时间。这意味着某些线程可能会比您“自然”期望的那样早或晚完成。
你的锁没有做任何事情。锁定块分隔尝试使用同一对象的代码段。在您的情况下,您不会在循环中两次使用相同的对象。处理的最后一个ID似乎是一致的这一事实可能完全是巧合。