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 演示。
更新好的,我确实发现它们在同一个线程上,但我仍然想知道锁是否阻止执行。 我无法想象它会。
如果ids
不包含重复项,则该锁不会阻止任何内容。但是,如果 ids
中有重复项,那么是的,锁上可能存在争用,因为不同的线程争夺对同一请求的访问。
只有当 id 排列成一条形
,以便您多次检索同一请求时,您的lock
才会阻止执行。由于每次打印不同的名称,因此这不应该是一个问题。
Parallel.For
使用线程池来处理循环。一旦它的一个线程是空闲的,它就会将其分配给下一个元素。这是不确定的,因为您不知道池中有多少线程,并且无法控制为每个线程提供的 CPU 时间。这意味着某些线程可能比您"自然"预期的迟早完成。
您的锁没有执行任何操作。锁块分隔尝试使用同一对象的代码段。在您的情况下,您不会在循环中两次使用同一个对象。最后处理的 ID 似乎一致这一事实可能纯粹是巧合。