Fua*_*kov 6 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"); }
}
}
Run Code Online (Sandbox Code Playgroud)
在Java中,除非将"完成"定义为volatile,否则代码将不安全.C#内存模型如何处理这个问题?
伙计们,谢谢大家的答案.非常感激.
嗯,有明显的竞争条件,他们都可以done
看作是假的并执行if
身体 - 无论记忆模型如何都是如此.使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);
}
}
Run Code Online (Sandbox Code Playgroud)
虽然在我当前的笔记本电脑上这已经终止,我已经使用了其他几乎完全相同的代码将永远运行的机器 - 它永远不会"看到" stop
第二个线程中的更改.
基本上,我试图避免编写无锁代码,除非它使用由真正了解其内容的人提供的更高级别的抽象 - 比如.NET 4中的Parallel Extensions.
有是一种方法,使这种密码锁和无正确的,虽然很容易使用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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里,值的变化及其测试作为一个单元执行:CompareExchange
如果当前为0,则仅将值设置为1,并返回旧值.因此,只有一个线程会看到返回值为0.
另外要记住的一点是:你的问题很模糊,因为你还没有定义"线程安全"的含义.我已经猜到了你的意图,但你从来没有说清楚.阅读Eric Lippert撰写的这篇博客文章 - 非常值得.
不,这不是线程安全的.您可能有一个线程检查condition(if(!done)
),另一个线程检查相同的条件,然后第一个线程执行代码块(done = true
)中的第一行.
您可以通过锁使其线程安全:
lock(this)
{
if(!done)
{
done = true;
Console.WriteLine("Done");
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
460 次 |
最近记录: |