为什么在C#Parallel.ForEach循环中,一个变量的递减会修改另一个变量的递增?
通过我的一些修改从运行代码 带有注释行的输出:为什么在C#Parallel.ForEach循环中,一个变量的递减会修改另一个变量的递增?,c#,linq,concurrency,lambda,task-parallel-library,C#,Linq,Concurrency,Lambda,Task Parallel Library,通过我的一些修改从运行代码 带有注释行的输出: //threadsRemaining = Interlocked.Decrement(ref concurrentThreads); 是“明显的”,即预期的: [00:00] Job 0 complete. 2 threads remaining. unsafeCount=2 [00:00] Job 1 complete. 1 threads remaining. unsafeCount=1 [00:00] Job 2 complete. 3 t
//threadsRemaining = Interlocked.Decrement(ref concurrentThreads);
是“明显的”,即预期的:
[00:00] Job 0 complete. 2 threads remaining. unsafeCount=2
[00:00] Job 1 complete. 1 threads remaining. unsafeCount=1
[00:00] Job 2 complete. 3 threads remaining. unsafeCount=3
[00:00] Job 3 complete. 4 threads remaining. unsafeCount=4
[00:00] Job 4 complete. 5 threads remaining. unsafeCount=5
[00:00] Job 5 complete. 6 threads remaining. unsafeCount=6
[00:01] Job 6 complete. 7 threads remaining. unsafeCount=7
[00:01] Job 8 complete. 8 threads remaining. unsafeCount=8
[00:01] Job 7 complete. 9 threads remaining. unsafeCount=9
[00:01] Job 9 complete. 10 threads remaining. unsafeCount=10
当取消注释上述行时,相同代码的输出为:
[00:00] Job 0 complete. 1 threads remaining. unsafeCount=1
[00:00] Job 1 complete. 0 threads remaining. unsafeCount=0
[00:00] Job 3 complete. 0 threads remaining. unsafeCount=0
[00:00] Job 2 complete. 1 threads remaining. unsafeCount=1
[00:00] Job 4 complete. 1 threads remaining. unsafeCount=1
[00:00] Job 5 complete. 1 threads remaining. unsafeCount=1
[00:01] Job 6 complete. 1 threads remaining. unsafeCount=1
[00:01] Job 8 complete. 1 threads remaining. unsafeCount=1
[00:01] Job 9 complete. 1 threads remaining. unsafeCount=1
[00:01] Job 7 complete. 0 threads remaining. unsafeCount=0
您能解释一下为什么递减一个变量threadsrein
会停止(或阻止)递增另一个unsafeCount
控制台应用程序的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace seParallelForEachKeepsSpawningNewThreads
{
public class Node
{
public Node Previous { get; private set; }
public Node(Node previous)
{
Previous = previous;
}
}
public class Program
{
public static void Main(string[] args)
{
DateTime startMoment = DateTime.Now;
int concurrentThreads = 0;
int unsafeCount = 0;
var jobs = Enumerable.Range(0, 10);
ParallelOptions po = new ParallelOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount
};
Parallel.ForEach(jobs, po, delegate(int jobNr)
{
int threadsRemaining = Interlocked.Increment(ref concurrentThreads);
unsafeCount++;
int heavyness = jobNr % 9;
//Give the processor and the garbage collector something to do...
List<Node> nodes = new List<Node>();
Node current = null;
//for (int y = 0; y < 1024 * 1024 * heavyness; y++)
for (int y = 0; y < 1024 * 4 * heavyness; y++)
{
current = new Node(current);
nodes.Add(current);
}
TimeSpan elapsed = DateTime.Now - startMoment;
//*****************
//threadsRemaining = Interlocked.Decrement(ref concurrentThreads);
Console.WriteLine("[{0:mm\\:ss}] Job {1} complete. {2} threads remaining. unsafeCount={2}",
elapsed, jobNr, threadsRemaining, unsafeCount);
});
Console.WriteLine("FINISHED");
Console.ReadLine();
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统线程;
使用System.Threading.Tasks;
命名空间separallelforeachkeepspawningnewthreads
{
公共类节点
{
公共节点前一个{get;private set;}
公共节点(上一个节点)
{
先前=先前;
}
}
公共课程
{
公共静态void Main(字符串[]args)
{
DateTime startMoment=DateTime.Now;
int concurrenthreads=0;
int unsafeCount=0;
变量作业=可枚举范围(0,10);
ParallelOptions po=新的ParallelOptions
{
MaxDegreeOfParallelism=Environment.ProcessorCount
};
Parallel.ForEach(作业、采购订单、代表(内部作业编号)
{
int threadsRemaining=联锁增量(参考concurrentThreads);
unsafeCount++;
整数权重=作业编号%9;
//给处理器和垃圾收集器一些事情做。。。
列表节点=新列表();
节点电流=零;
//对于(整数y=0;y<1024*1024*重;y++)
对于(整数y=0;y<1024*4*重;y++)
{
当前=新节点(当前);
节点。添加(当前);
}
TimeSpan Appeased=DateTime.Now-startMoment;
//*****************
//螺纹保持=联锁。减量(参考concurrentThreads);
Console.WriteLine(“[{0:mm\\:ss}]作业{1}已完成。{2}个线程剩余。未完成计数={2}”,
已用、作业编号、线程维护、未完成计数);
});
控制台。写入线(“完成”);
Console.ReadLine();
}
}
}
这就是问题所在:
Console.WriteLine(
"[{0:mm\\:ss}] Job {1} complete. {2} threads remaining. unsafeCount={2}",
elapsed, jobNr, threadsRemaining, unsafeCount);
最后一部分应该是
{3}
,而不是{2}
。你现在只是在打印线程维护
两次…该死的,我没有看到的一点代码;虽然很容易做到。哦…谢谢,速度很快,但我可以在6分钟内接受答案