【问题标题】:Why decrementing one variable modifies incrementing of another one in C# Parallel.ForEach loop?为什么递减一个变量会修改 C# Parallel.ForEach 循环中另一个变量的递增?
【发布时间】:2013-03-13 08:18:40
【问题描述】:

Parallel.ForEach keeps spawning new threads 运行代码并进行一些我的修改

带有注释行的输出:

//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

你能解释一下为什么减少一个变量 threadsRemainin 会停止(或阻止)增加另一个变量 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();
    }
  }
}

【问题讨论】:

    标签: c# linq concurrency lambda task-parallel-library


    【解决方案1】:

    这就是问题所在:

    Console.WriteLine(
        "[{0:mm\\:ss}] Job {1} complete. {2} threads remaining. unsafeCount={2}", 
        elapsed, jobNr, threadsRemaining, unsafeCount);
    

    最后一部分应该是{3},而不是{2}。你现在只是打印了两次threadsRemaining...

    【讨论】:

    • 该死,我没有查看的那段代码;不过很容易做到。
    • 糟糕...谢谢,速度很快,不过可以在 6 分钟内接受答复
    猜你喜欢
    • 1970-01-01
    • 2011-10-15
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多