我主要关心的是布尔标志......没有任何同步就可以安全地使用它吗?我在几个地方读到它是原子的(包括文档)。
class MyTask
{
private ManualResetEvent startSignal;
private CountDownLatch latch;
private bool running;
MyTask(CountDownLatch latch)
{
running = false;
this.latch = latch;
startSignal = new ManualResetEvent(false);
}
// A method which runs in a thread
public void Run()
{
startSignal.WaitOne();
while(running)
{
startSignal.WaitOne();
//... some code
}
latch.Signal();
}
public void Stop()
{
running = false;
startSignal.Set();
}
public void Start()
{
running = true;
startSignal.Set();
}
public void Pause()
{
startSignal.Reset();
}
public void Resume()
{
startSignal.Set();
}
}
这是以这种方式设计任务的安全方式吗?有任何建议,改进,评论吗?
注意:我写了我的自定义CountDownLatch
课,以防你想知道我从哪里获得它。
更新
这也是我的CountDownLatch:
public class CountDownLatch
{
private volatile int m_remain;
private EventWaitHandle m_event;
public CountDownLatch (int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException();
m_remain = count;
m_event = new ManualResetEvent(false);
if (m_remain == 0)
{
m_event.Set();
}
}
public void Signal()
{
// The last thread to signal also sets the event.
if (Interlocked.Decrement(ref m_remain) == 0)
m_event.Set();
}
public void Wait()
{
m_event.WaitOne();
}
}
答案 0 :(得分:48)
你最好将它标记为volatile
:
volatile关键字表示a 字段可能会被多个修改 并发执行线程。字段 声明为volatile的不是 受编译器优化的影响 假设由单个线程访问。这个 确保最新的价值 在任何时候都在现场。
但我会改变你的循环:
startSignal.WaitOne();
while(running)
{
//... some code
startSignal.WaitOne();
}
正如你的帖子中那样,“某些代码”可能会在线程停止时执行(即调用Stop时),这是意外的,甚至可能是错误的。
答案 1 :(得分:5)
布尔值在C#中是原子的,但是,如果你想在一个线程中修改它并在另一个线程中读取它,你至少需要将它标记为易失性。否则,读取线程实际上只能将其读入寄存器一次。
答案 2 :(得分:2)
答案 3 :(得分:0)
// A method which runs in a thread
public void Run()
{
startSignal.WaitOne();
while(running)
{
startSignal.WaitOne();
//... some code
}
latch.Signal();
}
您需要使用“startSignal.Set()”取消阻塞工作线程两次,以便执行while块中的代码。
这是故意的吗?