c# - 在VS的 Debug模式下使用netcore 3.1时,线程无序地排队

标签 c# multithreading debugging .net-core semaphore

测试环境

  • .netcore 3.1(.netcore 2.x未测试)
  • 在vs Studio中启动新的调试实例:expected。
  • 调试版本:没问题✔。
  • 发布版本:没问题✔。

  • .NET Framework 4.7.1(未测试其他版本)。
  • 在vs Studio中启动新的调试实例:没问题✔。
  • 调试版本:没问题✔。
  • 发布版本:没问题✔。


  • 可复制的代码:
    using System;
    using System.Collections.Concurrent;
    using System.Threading;
    
    namespace SignalTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 20; i++)
                {
                    new Thread(new ThreadStart(new Worker($"c{i % 3}", $"name{i}").Start)).Start();
                }
                Console.ReadKey();
            }
        }
    
    
        class Worker
        {
            public static ConcurrentDictionary<string, Semaphore> Semaphores  = new ConcurrentDictionary<string, Semaphore>();
    
            public string Name { get; set; }
            public string Code { get; set; }
    
            public int Count { get; private set; }
    
            public Worker(string code, string name)
            {
                Code = code;
                Name = name;
    
                Semaphores.TryAdd(Code, new Semaphore(1, 1));
            }
    
            public void Start()
            {
                while (true)
                {
                    try
                    {
                        WriteLog($"[{Code}][{Name}] Wait.");
    
                        Semaphores[Code].WaitOne();
                        WriteLog($"[{Code}][{Name}] Begin.");
    
                        WriteLog($"[{Code}][{Name}] Working => {++Count}!!!");
                        Thread.Sleep(500);
                    }
                    finally
                    {
                        WriteLog($"[{Code}][{Name}] Release.");
                        Semaphores[Code].Release();
                    }
                }
            }
    
            public void WriteLog(string msg)
            {
                if (Code == "c1")
                    Console.WriteLine(msg);
            }
        }
    }
    
    所需的输出应该是将所有c1-coded线程打印为1,然后打印2,然后为3 ...,但是在dotnetcore 3.1(VS Debug实例,Debug> Start New Instance)中,结果可能不是您想要的,一个错误?
    不受欢迎的输出片段之一可能是:
    [c1][name1] Working => 4!!!
    [c1][name1] Release.
    [c1][name1] Wait.
    [c1][name4] Begin.
    [c1][name4] Working => 4!!!
    [c1][name4] Release.
    [c1][name7] Begin.
    [c1][name7] Working => 4!!!
    [c1][name4] Wait.
    [c1][name7] Release.
    [c1][name7] Wait.
    [c1][name10] Begin.
    [c1][name10] Working => 2!!!
    [c1][name10] Release.
    [c1][name10] Wait.
    [c1][name13] Begin.
    [c1][name13] Working => 1!!!
    [c1][name13] Release.
    [c1][name13] Wait.
    [c1][name16] Begin.
    [c1][name16] Working => 1!!!
    [c1][name16] Release.
    [c1][name16] Wait.
    [c1][name19] Begin.
    [c1][name19] Working => 1!!!
    

    最佳答案

    如所有版本的Semaphore(和SemaphoreSlim)的documentation中所述,是否为.NET Core:

    There is no guaranteed order, such as FIFO or LIFO, in which blocked threads enter the semaphore.


    在您的示例中,假设[name1]输入了一个信号量,而所有其他线程都在等待。 [name1]输出1,并递增计数器。然后,任何等待线程都可以不按特定顺序进入。说它是name2。同时,name1已被阻止等待互斥。 name2 pritns 1,递增计数器。现在要点-不能保证name1在互斥体上等待再次输入,因为不能保证顺序。因此它进入,打印2,递增计数器。然后可以输入name3,并在该name1之后再次打印3,而其他线程仍为1。
    因此,您在完整的.net或没有调试器的情况下观察到的“正确”行为仅仅是快乐的巧合,这并不能保证会发生。因此,当它没有发生时-这不是错误。

    关于c# - 在VS的 Debug模式下使用netcore 3.1时,线程无序地排队,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64801231/

    相关文章:

    c# - 如何制作一个看起来自然的列表?

    c# - 使用 LINQ 按多个表中的多个属性有条件地对元素进行排序

    c# - 在读/写 Access 数据库时获得最少锁定时间的最佳方法

    c++ - OpenMP 多线程建议

    c++ - 在调试器内的 OS X 上启动 C++ 命令行工具的简单方法

    android - 如何从 CursorLoader 刷新光标?

    c# - 从 C# 中存储为字符串的两个数字中找出较大的数字

    android - 等待 RxJava 响应

    linux - Shell脚本,并行和多线程?

    c - 我如何跟踪内存分配?