c++ - Notifying a consumer thread before or after releasing the lock on the mutex? -
below listing 4.5 book c++ concurrency in action defines thread-safe queue using condition variables.
#include <mutex> #include <condition_variable> #include <queue> #include <memory> template<typename t> class threadsafe_queue { private: mutable std::mutex mut; std::queue<t> data_queue; std::condition_variable data_cond; public: threadsafe_queue() {} threadsafe_queue(threadsafe_queue const& other) { std::lock_guard<std::mutex> lk(other.mut); data_queue=other.data_queue; } void push(t new_value) { std::lock_guard<std::mutex> lk(mut); data_queue.push(new_value); data_cond.notify_one(); } void wait_and_pop(t& value) { std::unique_lock<std::mutex> lk(mut); data_cond.wait(lk,[this]{return !data_queue.empty();}); value=data_queue.front(); data_queue.pop(); } std::shared_ptr<t> wait_and_pop() { std::unique_lock<std::mutex> lk(mut); data_cond.wait(lk,[this]{return !data_queue.empty();}); std::shared_ptr<t> res(std::make_shared<t>(data_queue.front())); data_queue.pop(); return res; } bool try_pop(t& value) { std::lock_guard<std::mutex> lk(mut); if(data_queue.empty) return false; value=data_queue.front(); data_queue.pop(); } std::shared_ptr<t> try_pop() { std::lock_guard<std::mutex> lk(mut); if(data_queue.empty()) return std::shared_ptr<t>(); std::shared_ptr<t> res(std::make_shared<t>(data_queue.front())); data_queue.pop(); return res; } bool empty() const { std::lock_guard<std::mutex> lk(mut); return data_queue.empty(); } }; int main() {} in push function, thread being notified while mutex still locked. isn't better notify popper threads right after mutex released. example, this:
void push(t new_value) { { std::lock_guard<std::mutex> lk(mut) data_queue.push(new_value); } data_cond.notify_one(); } i aware functionally same thing. i'm thinking in original case, consumer thread receive false notification makes try locking mutex more once. however, in second case, avoid waking consumer thread early, , therefore, tries lock mutex can successful in first time.
that not matter, end result going same. if first notify , unlock mutex, listening thread notified, still locked on mutex, once mutex unlocked, thread proceed.
if first unlock mutex, thread not know condition ready until notified , waiting on condition variable (barred spurious wake ups).
in end, listening thread proceed once both conditions met - mutex unlocked, variable notified.
Comments
Post a Comment