简体   繁体   English

在设置条件变量之前,我是否必须锁定以检查与条件变量一起使用的工作可用标志,如果是,为什么?

[英]Do I have to lock to check a work-available flag used with a condition variable before setting it, and if so why?

I have a worker thread in a thread pool that behaves like so:我在线程池中有一个工作线程,其行为如下:

while (running)
{
    std::unique_lock<std::mutex> lock(m_mutex);
    m_condition.wait(lock, [&] { return m_workAvailable; });
    m_workAvailable = false;
    lock.unlock();

    // (Perform work...)
}

When I drop work into this worker thread, it looks like so:当我将工作放到这个工作线程中时,它看起来像这样:

// (enqueue the actual work item...)

if (!m_workAvailable)
{
  std::lock_guard<std::mutex> lock(m_mutex);
  m_workAvailable = true;
}

m_condition.notify_one();

After seeing the behavior of this code in practice I'm guessing that there is some kind of concurrency bug related to the在实践中看到此代码的行为后,我猜测存在某种与

if(! m_workAvailable)

check here, which is meant to bypass contention for the mutex unless necessary.在这里检查,这意味着除非必要,否则会绕过互斥锁的争用。 But if this is so, I don't actually see the scenario that would cause this problem.但如果是这样,我实际上并没有看到会导致这个问题的场景。

[ Update : I have tried this with m_workAvailable being both bool and volatile bool . [更新:我已经尝试过m_workAvailable既是bool又是volatile bool I have not as yet tried std::atomic<bool> , though as far as I understand that wouldn't be fundamentally different from volatile bool here.我还没有尝试过std::atomic<bool> ,但据我所知,这与这里的volatile bool并没有根本的不同。 ] ]

Questions:问题:

  1. Is this indeed a concurrency bug?这确实是一个并发错误吗?
  2. If so, why -- what does this allow to go wrong?如果是这样,为什么 - 这允许 go 出错?
  3. If so, is there any way of doing what I'm doing here that doesn't require me to lock the mutex every single time a piece of work comes in?如果是这样,有什么方法可以做我在这里做的事情,而不需要我在每次工作进入时都锁定互斥锁?

Is this indeed a concurrency bug?这确实是一个并发错误吗?

Yes.是的。

If so, why -- what does this allow to go wrong?如果是这样,为什么 - 这允许 go 出错?

It's undefined behavior.这是未定义的行为。 The standards don't say what happens if a non-atomic type is accessed by one thread while another thread is, or might be, modifying it.标准没有说明如果一个线程访问非原子类型而另一个线程正在或可能正在修改它会发生什么。 Your code does that.你的代码就是这样做的。 So it can break in any imaginable way.所以它可以以任何可以想象的方式破裂。

If so, is there any way of doing what I'm doing here that doesn't require me to lock the mutex every single time a piece of work comes in?如果是这样,有什么方法可以做我在这里做的事情,而不需要我在每次工作进入时都锁定互斥锁?

Yes, Do this:是的,这样做:

{
     std::lock_guard<std::mutex> lock(m_mutex);
     m_workAvailable = true;
     m_condition.notify_one();
}

Your platform, if it has a good implementation, will detect that the mutex is already held when you call notify_one and avoid synchronizing again.您的平台,如果它具有良好的实现,将在您调用notify_one时检测到互斥锁已被持有并避免再次同步。 The net effect will be roughly the same as not acquiring the mutex during the set of m_workAvailable if the mutex isn't contended.如果互斥锁没有被争用,净效果将与在m_workAvailable集合期间不获取互斥锁大致相同。 (If it is contended, the cost is unavoidable anyway.) (如果有争议,无论如何成本是不可避免的。)

I have not as yet tried std::atomic<bool> , though as far as I understand that wouldn't be fundamentally different from volatile bool here.我还没有尝试过std::atomic<bool> ,但据我所知,这与这里的volatile bool并没有根本的不同。

Umm, huh?嗯,嗯? What threading standard defines the behavior when a volatile bool is accessed in one thread while another thread is, or might be, modifying it?什么线程标准定义了在一个线程中访问volatile bool而另一个线程正在或可能正在修改它时的行为? I don't know of any except Microsoft Visual Studio.我不知道除了 Microsoft Visual Studio 之外的任何东西。 By contrast, std::atomic<bool> has well-defined semantics in that case.相比之下, std::atomic<bool>在这种情况下具有明确定义的语义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在调用 condition_variable.notify_one() 之前我必须获取锁吗? - Do I have to acquire lock before calling condition_variable.notify_one()? 为什么在进行条件变量notify之前我们需要一个空的std :: lock_guard? - Why do we need an empty std::lock_guard before doing condition variable notify? 在调用 condition_variable::notify() 之前是否需要锁定互斥锁? - Do I need to lock the mutex before calling condition_variable::notify()? 为什么必须将错误状态标志设置为goodbit才能起作用? - Why do I have to set the error state flag to goodbit in order for this to work? 在条件变量上发出信号之前是否必须锁定互斥锁? - Is it mandatory to lock mutex before signaling on condition variable? 为什么我不能在if条件中做这样的变量定义 - why I cannot do such a variable definition in if condition std :: unique_lock和std :: condition_variable如何工作 - How do std::unique_lock and std::condition_variable work 为什么必须为boost :: condition_variable使用boost :: mutex? - why must I have a boost::mutex for boost::condition_variable? 当我有太多可用内存时,为什么会得到std :: bad_alloc - Why am I getting std::bad_alloc when I have so much free memory available 那么,为什么我必须在基类中定义虚函数? - So, why do I have to define virtual function in a base class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM