{"id":4758,"date":"2016-05-17T06:01:23","date_gmt":"2016-05-17T06:01:23","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/condition-variables\/"},"modified":"2023-06-26T12:56:56","modified_gmt":"2023-06-26T12:56:56","slug":"condition-variables","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/condition-variables\/","title":{"rendered":"Condition Variables"},"content":{"rendered":"<p>Condition variables allow us to synchronize threads via notifications. So, you can implement workflows like sender\/receiver or producer\/consumer. In such a workflow, the receiver waits for the sender&#8217;s notification. If the receiver gets the notification, it continues its work.<\/p>\n<p><!--more--><\/p>\n<h2>std::condition_variable<\/h2>\n<p>The condition variable can fulfill the roles of a sender or a receiver. As a sender, it can notify one or more receivers.<\/p>\n<p>That&#8217;s all you have to know to use condition variables.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ conditionVariable.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;condition_variable&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;mutex&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;thread&gt;<\/span>\r\n\r\nstd::mutex mutex_;\r\nstd::condition_variable condVar;\r\n\r\n<span style=\"color: #2b91af;\">void<\/span> doTheWork(){\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Processing shared data.\"<\/span> &lt;&lt; std::endl;\r\n}\r\n\r\n<span style=\"color: #2b91af;\">void<\/span> waitingForWork(){\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Worker: Waiting for work.\"<\/span> &lt;&lt; std::endl;\r\n\r\n    std::unique_lock&lt;std::mutex&gt; lck(mutex_);\r\n    condVar.wait(lck);\r\n    doTheWork();\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Work done.\"<\/span> &lt;&lt; std::endl;\r\n}\r\n\r\n<span style=\"color: #2b91af;\">void<\/span> setDataReady(){\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Sender: Data is ready.\"<\/span>  &lt;&lt; std::endl;\r\n    condVar.notify_one();\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::<span style=\"color: #0000ff;\">thread<\/span> t1(waitingForWork);\r\n  std::<span style=\"color: #0000ff;\">thread<\/span> t2(setDataReady);\r\n\r\n  t1.join();\r\n  t2.join();\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n  \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The program has two child threads:<span style=\"font-family: courier new,courier;\">&nbsp;t1<\/span> and <span style=\"font-family: courier new,courier;\">t2<\/span>. They get their <em>callable&nbsp;payload (functions or functors)<\/em>&nbsp;<span style=\"font-family: courier new,courier;\">waitingForWork<\/span> and <span style=\"font-family: courier new,courier;\">setDataReady<\/span> in lines 33 and 34. The function <span style=\"font-family: courier new,courier;\">setDataReady<\/span> notifies &nbsp;&#8211; using the condition variable <span style=\"font-family: courier new,courier;\">condVar<\/span>&nbsp;&#8211; that it is done with the preparation of the work: <span style=\"font-family: courier new,courier;\">condVar.notify_one()<\/span>. While holding the lock, thread <span style=\"font-family: courier new,courier;\">t2<\/span> awaits its notification: <span style=\"font-family: courier new,courier;\">condVar.wait(lck)<\/span>. The waiting thread always performs the same steps. It wakes up, tries to get the lock, checks if it&#8217;s holding it, if the notifications arrived, and, in case of failure, &nbsp;puts itself back to sleep. In case of success, the thread leaves the endless loop and continues with its work.<\/p>\n<p>&nbsp;<\/p>\n<p>The output of the program is not so thrilling. That was my first impression. But wait.&nbsp;<\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4756\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/05\/conditionVariable.png\" alt=\"conditionVariable\" width=\"527\" height=\"227\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/05\/conditionVariable.png 527w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/05\/conditionVariable-300x129.png 300w\" sizes=\"auto, (max-width: 527px) 100vw, 527px\" \/><\/h2>\n<\/p>\n<h2>Spurious wakeup<\/h2>\n<p>The devil is in the details. It can happen that the&nbsp;receiver finished its task before the sender sent its notification. How is that possible? The receiver is susceptible to spurious wakeups. So the receiver wakes up, although no notification happens. I had to add a predicate to the wait method to protect it from this. That&#8217;s precisely what I had done in the following example<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ conditionVariableFixed.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;condition_variable&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;mutex&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;thread&gt;<\/span>\r\n\r\nstd::mutex mutex_;\r\nstd::condition_variable condVar;\r\n\r\n<span style=\"color: #2b91af;\">bool<\/span> dataReady;\r\n\r\n<span style=\"color: #2b91af;\">void<\/span> doTheWork(){\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Processing shared data.\"<\/span> &lt;&lt; std::endl;\r\n}\r\n\r\n<span style=\"color: #2b91af;\">void<\/span> waitingForWork(){\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Worker: Waiting for work.\"<\/span> &lt;&lt; std::endl;\r\n\r\n    std::unique_lock&lt;std::mutex&gt; lck(mutex_);\r\n    condVar.wait(lck,[]{<span style=\"color: #0000ff;\">return<\/span> dataReady;});\r\n    doTheWork();\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Work done.\"<\/span> &lt;&lt; std::endl;\r\n}\r\n\r\n<span style=\"color: #2b91af;\">void<\/span> setDataReady(){\r\n    std::lock_guard&lt;std::mutex&gt; lck(mutex_);\r\n    dataReady=true;\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Sender: Data is ready.\"<\/span>  &lt;&lt; std::endl;\r\n    condVar.notify_one();\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::<span style=\"color: #0000ff;\">thread<\/span> t1(waitingForWork);\r\n  std::<span style=\"color: #0000ff;\">thread<\/span> t2(setDataReady);\r\n\r\n  t1.join();\r\n  t2.join();\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n  \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The key difference from the first example <span style=\"font-family: courier new,courier;\">conditionVariable.cpp<\/span> is the boolean<span style=\"font-family: courier new,courier;\">&nbsp;dataReady<\/span> used in line 11 as an additional condition. <span style=\"font-family: courier new,courier;\">dataReady<\/span> is set to <span style=\"font-family: courier new,courier;\">true<\/span> in line 28. It is checked&nbsp;in the function <span style=\"font-family: courier new,courier;\">waitingForWork: condVar.waint(lck,[]return dataReady;})<\/span>. The<span style=\"font-family: 'courier new', courier;\"> wait()<\/span> method has an additional overload that accepts a predicate. A predicate is a callable returning&nbsp;<span style=\"font-family: courier new,courier;\">true<\/span> or <span style=\"font-family: courier new,courier;\">false.<\/span> In this example, the callable is a lambda function. So, the condition variable checks whether the predicate is <span style=\"font-family: courier new,courier;\">true<\/span>&nbsp;or if the notification happened.<\/p>\n<p>A short remark &#8211; &nbsp;<span style=\"font-family: courier new,courier;\">dataReady.<\/span> <span style=\"font-family: courier new,courier;\">dataReady<\/span> is a shared variable that will be changed. So I had to protect it with a lock. Because thread <span style=\"font-family: courier new,courier;\">t1<\/span>&nbsp;sets and releases the lock just once,&nbsp;<span style=\"font-family: courier new,courier;\">std::lock_guard<\/span> is fine for that job. That will not hold for thread<span style=\"font-family: courier new,courier;\"> t2<\/span>. The wait method will continuously lock and unlock the mutex. So I need the more powerful lock:&nbsp;<span style=\"font-family: courier new,courier;\">std::unique_lock.<\/span><\/p>\n<p>But that&#8217;s not all. Condition variables have a lot of challenges. They must be protected by locks and are susceptible to spurious wakeups. Most use cases are easier to solve with tasks. More about tasks in the next post.<\/p>\n<h2><span style=\"color: #000000;\"> <a id=\"LostWakeup\" style=\"color: #000000;\">Lost wakeup<\/a><\/span><\/h2>\n<p>&nbsp;<\/p>\n<p>The meanness of condition variables goes on. About every 10th execution of the <span style=\"font-family: courier new,courier;\">conditionVariable.cpp<\/span>&nbsp;something strange happens. The program blocks.<span style=\"color: #000000;\"><br \/> <\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4757\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/05\/conditionVariableWithoutPredicate.png\" alt=\"conditionVariableWithoutPredicate\" width=\"527\" height=\"185\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/05\/conditionVariableWithoutPredicate.png 527w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/05\/conditionVariableWithoutPredicate-300x105.png 300w\" sizes=\"auto, (max-width: 527px) 100vw, 527px\" \/><\/p>\n<p>I have no idea what&#8217;s going on. This phenomenon contradicts my intuition of condition variables. Did I mention that I don&#8217;t like condition variables? With the support of <a href=\"https:\/\/www.justsoftwaresolutions.co.uk\/\">Anthony Williams<\/a>, I solved the riddle.<\/p>\n<p>The problem is that the notification gets lost if the sender sends its notification before the receiver gets to a wait state.&nbsp;The C++ standard describes condition variables as synchronization mechanisms at the same time:&nbsp;<span class=\"hiddenGrammarError\">&#8220;<\/span><span class=\"hiddenSpellError\">The<\/span> <span class=\"hiddenSpellError\">condition<\/span>_variable <span class=\"hiddenSpellError\">class<\/span> <span class=\"hiddenSpellError\">is<\/span> a <span class=\"hiddenSpellError\">synchronization<\/span> primitive <span class=\"hiddenSpellError\">that<\/span> <span class=\"hiddenSpellError\">can<\/span> <span class=\"hiddenSpellError\">be<\/span> <span class=\"hiddenSpellError\">used<\/span> <span class=\"hiddenSpellError\">to<\/span> block a <span class=\"hiddenSpellError\">thread<\/span>, <span class=\"hiddenSpellError\">or<\/span> multiple <span class=\"hiddenSpellError\">threads<\/span> <span class=\"hiddenSpellError\">at<\/span> <span class=\"hiddenSpellError\">the<\/span> <span class=\"hiddenSpellError\">same<\/span> time, <span class=\"hiddenGrammarError\">&#8230;<\/span><span class=\"hiddenGrammarError\">&#8220;<\/span>. So the notification gets lost, and the receiver is waiting and waiting and &#8230;.<\/p>\n<p>How can this issue be solved? The predicate that got rid of spurious wakeups will also help with lost ones. If the predicate is <span style=\"font-family: courier new,courier;\">true,<\/span> the receiver can continue its work independently of the sender&#8217;s notification. The variable <span style=\"font-family: courier new,courier;\">dataReady<\/span> is like a memory. Because as far as the variable data in line 28 is set to <span style=\"font-family: courier new,courier;\">true,<\/span> the receiver assumes in line 21 that the notification was delivered.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>With tasks, multithreading in C++ get a lot easier. Stay tuned for the <a href=\"https:\/\/www.modernescpp.com\/index.php\/tasks\">next post<\/a>. (<strong>Proofreader Alexey Elymanov<\/strong>)<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Condition variables allow us to synchronize threads via notifications. So, you can implement workflows like sender\/receiver or producer\/consumer. In such a workflow, the receiver waits for the sender&#8217;s notification. If the receiver gets the notification, it continues its work.<\/p>\n","protected":false},"author":21,"featured_media":4756,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[366],"tags":[451],"class_list":["post-4758","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-multithreading","tag-condition-variables"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4758","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=4758"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4758\/revisions"}],"predecessor-version":[{"id":6979,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4758\/revisions\/6979"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/4756"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=4758"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=4758"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=4758"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}