关于您粘贴的 sn-p 代码的串行执行,您的假设是不正确的。
Parallel.ForEach (windows, (win) =>
{
lock (syncObject) // now it should execute sequentially?
{
// do something with someArray
}
});
您放在那里的lock 确保一次只有一个线程可以访问代码的这个特定关键部分(包含在lock(syncObject) {} 中的代码,但并不意味着语句本身将执行顺序。
将您的 Parallel.ForEach 替换为 ThreadPool 可能会更容易理解:
foreach(var item in list)
{
ThreadPool.QueueUserWorkItem(i =>
{
lock (syncObject)
{
// do something with i here
}
}, item);
}
这两个 sn-ps 或多或少是等价的。如您所见,您首先为列表中的每个项目启动一个线程,然后在线程内部,您获得锁,这将确保没有其他线程可以访问该封闭的关键部分。然而,这并不能保证它们是按顺序完成的并且顺序会被保留。
线程池中线程的执行顺序不受您的控制,因此,使用线程池无法保证任何顺序(至少,不是传统意义上的)。
现在让我们看一下这个例子,希望能让事情变得更清楚:
var syncObject = new Object();
var list = new List<int>();
for(int i=0;i<20;i++)
{
list.Add(i);
}
Parallel.ForEach(list, item =>
{
Console.WriteLine(item + " waiting to be executed on " + Thread.CurrentThread.ManagedThreadId);
lock (syncObject) // now it should execute sequentially?
{
Console.WriteLine(item + " executing on " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(100);
}
});
本次执行的结果将与此类似:
0 waiting to be executed on 1
0 executing on 1
2 waiting to be executed on 4
4 waiting to be executed on 6
10 waiting to be executed on 9
12 waiting to be executed on 5
8 waiting to be executed on 10
16 waiting to be executed on 7
6 waiting to be executed on 8
14 waiting to be executed on 3
1 waiting to be executed on 11
2 executing on 4
10 executing on 9
3 waiting to be executed on 4
11 waiting to be executed on 9
16 executing on 7
14 executing on 3
17 waiting to be executed on 7
15 waiting to be executed on 3
8 executing on 10
9 waiting to be executed on 10
4 executing on 6
12 executing on 5
5 waiting to be executed on 6
6 executing on 8
13 waiting to be executed on 5
1 executing on 1
7 waiting to be executed on 8
3 executing on 4
18 waiting to be executed on 1
11 executing on 9
17 executing on 7
15 executing on 3
9 executing on 10
5 executing on 6
13 executing on 5
7 executing on 8
18 executing on 1
19 waiting to be executed on 1
19 executing on 1
如您所见,可能有多个线程等待进入临界区,但在任何给定时间只有一个线程将执行lock 内的语句。 但是由于 ThreadPool 线程管理和调度的性质,执行的顺序是随机的而不是连续的。