gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 20:55:25 24 4
gpt4 key购买 nike

我正在尝试学习 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com