代码之家  ›  专栏  ›  技术社区  ›  Kiril

使用布尔标志阻止线程在C中运行是否安全?#

  •  35
  • Kiril  · 技术社区  · 14 年前

    我主要关心的是布尔标记…在没有任何同步的情况下使用它是否安全?我在一些地方读到它是原子的(包括文档)。

    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 以防你想知道我从哪儿弄来的。

    更新:
    这也是我的倒计时:

    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();
        }
    }
    
    4 回复  |  直到 14 年前
        1
  •  47
  •   Remus Rusanu    14 年前

    你最好记下来 volatile 虽然:

    volatile关键字表示 字段可能被多个 同时执行线程。领域 被宣布为不稳定的 以编译器优化为准 假定由单个线程访问。这个 确保最新的价值 随时出现在现场。

    但我会改变你的循环:

        startSignal.WaitOne();
        while(running)
        {
            //... some code
            startSignal.WaitOne();
        }
    

    正如您的帖子中所说,当线程 停止 (即当调用stop时)这是意外的,甚至可能是不正确的。

        2
  •  5
  •   Michael Burr    14 年前

    布尔值在C中是原子的,但是,如果您想在一个线程中修改它并在另一个线程中读取它,则至少需要将其标记为volatile。否则,读取线程实际上只能将其读取一次到寄存器中。

        3
  •  2
  •   Kevin Sylvestre    14 年前
        4
  •  0
  •   akapet    14 年前

    顺便说一句,我刚刚注意到这部分代码:

    // A method which runs in a thread
        public void Run()
        {
            startSignal.WaitOne();
            while(running)
            {
                startSignal.WaitOne();
                //... some code
            }
            latch.Signal();
        }
    

    要执行while块中的代码,需要使用“startsignal.set()”两次解除工作线程的阻塞。

    这是故意的吗?