Why do I need to acquire a lock to modify a shared “atomic” variable before notifying condition_variable

后端 未结 2 1920
忘了有多久
忘了有多久 2020-12-06 06:22

Accoding to cppreference.com:

The thread that intends to modify the variable has to

  1. acquire a std::mutex (typically via std::lock_
相关标签:
2条回答
  • 2020-12-06 06:45

    Found a very good explanation about this issue in another thread. Take a loot at

    Questions where asked below about race conditions.

    If the data being communicated is atomic, can't we do without the mutex on the "send" side?

    at the end.

    0 讨论(0)
  • 2020-12-06 06:54

    As noted in Yakk's answer to the question you linked to it is to protect against this sequence of events causing a missed wake-up:

      1. Thread A locks the mutex.
      1. Thread A calls the lambda's closure which does m_hasEvents.load(std::memory_order_relaxed); and returns the value false.
      1. Thread A is interrupted by the scheduler and Thread B starts to run.
      1. Thread B pushes an event into the queue and stores to s_hasEvent
      1. Thread B runs s_cv.notify_one().
      1. Thread B is interrupted by the scheduler and Thread A runs again.
      1. Thread A evaluates the false result returned by the closure, deciding there are no pending events.
      1. Thread A blocks on the condition variable, waiting for an event.

    This means the notify_one() call has been missed, and the condition variable will block even though there is an event ready in the queue.

    If the update to the shared variable is done while the mutex is locked then it's not possible for the step 4 to happen between steps 2 and 7, so the condition variable's check for events gets a consistent result. With a mutex used by the publisher and the consumer either the store to s_hasEvent happens before step 1 (and so the closure loads the value true and never blocks on the condition variable) or it happens after step 8 (and so the notify_one() call will wake it up).

    0 讨论(0)
提交回复
热议问题