c# - 以下 C# 代码线程安全吗?

标签 c# multithreading thread-safety

我正在尝试学习 C# 中的线程。今天我在 http://www.albahari.com/threading/ 播下以下代码:

class ThreadTest
{
  bool done;

  static void Main()
  {
    ThreadTest tt = new ThreadTest();   // Create a common instance
    new Thread (tt.Go).Start();
    tt.Go();
  }

  // Note that Go is now an instance method
  void Go() 
  {
     if (!done) { done = true; Console.WriteLine ("Done"); }
  }
}

在 Java 中,除非您将“完成”定义为易变的,否则代码将不安全。 C# 内存模型如何处理这个问题?

伙计们,谢谢大家的回答。非常感激。

最佳答案

好吧,他们都可以看到明显的竞争条件 done为 false 并执行 if body - 无论内存模型如何,都是如此。制作done volatile 不会解决这个问题,它也不会在 Java 中解决这个问题。

但是,是的,在一个线程中所做的更改可能发生但在另一个线程中可见是可行的。这取决于 CPU 体系结构等。作为我的意思的一个例子,考虑这个程序:

using System;
using System.Threading;

class Test
{
    private bool stop = false;

    static void Main()
    {
        new Test().Start();
    }

    void Start()
    {
        new Thread(ThreadJob).Start();
        Thread.Sleep(500);
        stop = true;
    }

    void ThreadJob()
    {
        int x = 0;
        while (!stop)
        {
            x++;
        }
        Console.WriteLine("Counted to {0}", x);
    }
}

虽然在我的当前笔记本电脑上这确实会终止,但我使用过其他机器,在这些机器上几乎完全相同的代码会永远运行 - 它永远不会“看到”对 stop 的更改。在第二个线程中。

基本上,我尽量避免编写无锁代码,除非它使用真正了解他们的东西的人提供的更高级别的抽象——比如 .NET 4 中的并行扩展。

不过, 有一种方法可以使此代码无锁并轻松更正,使用 Interlocked .例如:

class ThreadTest
{
  int done;

  static void Main()
  {
    ThreadTest tt = new ThreadTest();   // Create a common instance
    new Thread (tt.Go).Start();
    tt.Go();
  }

  // Note that Go is now an instance method
  void Go() 
  {
     if (Interlocked.CompareExchange(ref done, 1, 0) == 0) 
     {
         Console.WriteLine("Done");
     }
  }
}

此处值的更改及其测试作为一个单元执行:CompareExchange只有当前为 0 时才会将值设置为 1,并返回 值。因此只有一个线程会看到返回值 0。

要记住的另一件事:您的问题相当模棱两可,因为您尚未定义“线程安全”的含义。我猜到了你的意图,但你从来没有说清楚。阅读this blog post by Eric Lippert - 这是非常值得的。

关于c# - 以下 C# 代码线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5983635/

相关文章:

c# - 在 C# 中扩展抽象类

来自异步线程的 Java 同步数据库管理器

c - 以原子方式将值存储在 uint8_t (C)

c++ - 如何在 C++ 中使共享内存线程安全的容器

c# - 不继承共享属性

c# - 使用静态 Regex.IsMatch 与创建 Regex 实例

c# - Unity C# - 在一个点周围随机生成游戏对象

java - 如何断言该方法不是同时运行(或者在并发时快速失败)?

java - java中的单例模式。惰性初始化

java - Struts2如何在没有线程的情况下获得性能?