当另一个线程可能设置它(最多一次)时,可以读取共享布尔标志而不锁定它吗?

2022-01-19 00:00:00 multithreading boolean locking c++ monitor

我希望我的线程更优雅地关闭,所以我尝试实现一个简单的信号机制.我不认为我想要一个完全事件驱动的线程,所以我有一个工作人员可以使用关键部分 Monitor 优雅地停止它(相当于 C# lock我相信):

I would like my thread to shut down more gracefully so I am trying to implement a simple signalling mechanism. I don't think I want a fully event-driven thread so I have a worker with a method to graceully stop it using a critical section Monitor (equivalent to a C# lock I believe):

绘图线程.h

class DrawingThread {
    bool stopRequested;
    Runtime::Monitor CSMonitor;
    CPInfo *pPInfo;
    //More..
}

绘图线程.cpp

void DrawingThread::Run() {
    if (!stopRequested)
        //Time consuming call#1
    if (!stopRequested) {
        CSMonitor.Enter();
        pPInfo = new CPInfo(/**/);
        //Not time consuming but pPInfo must either be null or constructed. 
        CSMonitor.Exit();
    }
    if (!stopRequested) {
        pPInfo->foobar(/**/);//Time consuming and can be signalled
    }
    if (!stopRequested) {
        //One more optional but time consuming call.
    }
}


void DrawingThread::RequestStop() {
    CSMonitor.Enter();
    stopRequested = true;
    if (pPInfo) pPInfo->RequestStop();
    CSMonitor.Exit();
}

我了解(至少在 Windows 中)Monitor/lock 是最便宜的线程同步原语,但我希望避免过度使用.我应该包装这个布尔标志的每次读取吗?它被初始化为 false,并且仅在请求停止时设置一次为 true(如果在任务完成之前请求它).

I understand (at least in Windows) Monitor/locks are the least expensive thread synchronization primitive but I am keen to avoid overuse. Should I be wrapping each read of this boolean flag? It is initialized to false and only set once to true when stop is requested (if it is requested before the task completes).

我的导师建议保护甚至 bool 的,因为读/写可能不是原子的.我觉得这个一击旗是证明规则的例外?

My tutors advised to protect even bool's because read/writing may not be atomic. I think this one shot flag is the exception that proves the rule?

推荐答案

在没有同步的情况下读取可能在不同线程中修改的内容是永远不会好的.需要什么级别的同步取决于您实际阅读的内容.对于原始类型,您应该查看原子读取,例如std::atomic<bool>.

It is never OK to read something possibly modified in a different thread without synchronization. What level of synchronization is needed depends on what you are actually reading. For primitive types, you should have a look at atomic reads, e.g. in the form of std::atomic<bool>.

始终需要同步的原因是处理器将可能在高速缓存行中共享数据.如果没有同步,则没有理由将此值更新为可能在不同线程中更改的值.更糟糕的是,如果没有同步,如果存储在该值附近的内容被更改和同步,它可能会写入错误的值.

The reason synchronization is always needed is that the processors will have the data possibly shared in a cache line. It has no reason to update this value to a value possibly changed in a different thread if there is no synchronization. Worse, yet, if there is no synchronization it may write the wrong value if something stored close to the value is changed and synchronized.

相关文章