c# - 为什么当 Console.WriteLine 在下一行时 i++ 表现得像线程安全操作

标签 c# multithreading thread-safety

我在读一本关于 C# 的书时遇到一个声明,该声明声称以下代码将对共享的 count 变量产生 20000 次增量,并且 count 的最终值将为 20000。 当我运行它时,ii 总是打印 20000。据我所知,count++ 不是线程安全操作,当 Console.WriteLine 被删除时,打印结果符合预期——在所有情况下都不是 20000。 有人能解释一下为什么在这种情况下 count 的最终值是 20000 吗?以及为什么 count++ 充当线程安全操作。

    private static void testTask()
    {
        Task t1 = new Task(() =>
          {
              for (int i = 0; i < 10000; i++)
              {
                  count++;
                  Console.WriteLine("Thread 1 - {0}", count);
              }
          }
       );

        Task t2 = new Task(() =>
         {
             for (int i = 0; i < 10000; i++)
             {
                 count++;
                 Console.WriteLine("Thread 2 - {0}", count);
             }
         }
      );
        t1.Start();
        t2.Start();
        Task.WaitAll(t1, t2);
        Console.WriteLine("Count - {0}", count);
    }

最佳答案

这实际上并不能确保安全,您只是影响了时间,从而降低了看到效果的几率。执行 i++ 所花费的时间是 Console.Write 所花费时间的一小部分,因此您增加了在一个线程中执行 i++ 的几率一个 Console.Write 在另一个。运行它足够多次,您可能会发现相同的行为。


class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            testTask();
        }

        Console.Read();
    }

    private static void testTask()
    {
        int count = 0;

        Task t1 = new Task(() =>
        {
            for (int i = 0; i < 10000; i++)
            {
                count++;
                //Console.WriteLine("Thread 1 - {0}", count);
            }
        }
       );

        Task t2 = new Task(() =>
        {
            for (int i = 0; i < 10000; i++)
            {
                count++;
                //Console.WriteLine("Thread 2 - {0}", count);
            }
        }
      );
        t1.Start();
        t2.Start();
        Task.WaitAll(t1, t2);
        Console.WriteLine("Count - {0}", count);
    }
}

关于c# - 为什么当 Console.WriteLine 在下一行时 i++ 表现得像线程安全操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22710697/

相关文章:

c# - IS vs. AS vs. IsAssignableFrom - 检查对象类型和接口(interface)时有什么区别?

multithreading - Google Guava Cache 是否在同一个线程上加载?

c# - 如何在 ASP.NET 中缓存?

c# - 正则表达式特周

c# - Linq ToList() 执行

C# 控制线程(恢复/挂起)

java - 如何在Java中连续检查文件是否存在? [复制]

Java多线程通信,生产者-消费者-取消,四个线程交互。任何干净稳健的方法都可以做到这一点

c# - 具有抽象保护成员的多线程?

ios - 在多次调用 loadFileRepresentation 完成后运行 block