{"id":4781,"date":"2016-06-11T14:24:00","date_gmt":"2016-06-11T14:24:00","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/thread-synchronization-with-condition-variables-or-tasks\/"},"modified":"2023-06-26T12:54:36","modified_gmt":"2023-06-26T12:54:36","slug":"thread-synchronization-with-condition-variables-or-tasks","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/thread-synchronization-with-condition-variables-or-tasks\/","title":{"rendered":"Thread Synchronization with Condition Variables or Tasks"},"content":{"rendered":"<p>In case you use promise and future to synchronize threads, they have much in common with <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/condition-variable\">condition variables<\/a>. But most of the time, tasks are the better choice.<\/p>\n<p><!--more--><\/p>\n<h2>Synchronization of threads<\/h2>\n<p>To get the big picture, get the facts. The table compares condition variables with tasks (promise and future).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4779\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/ConditionVariableVersusTask.png\" alt=\"ConditionVariableVersusTask\" width=\"600\" height=\"208\" style=\"margin: 15px;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/ConditionVariableVersusTask.png 707w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/ConditionVariableVersusTask-300x104.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>The benefit of a condition variable to a promise and future is that you can use condition variables to synchronize threads multiple times. In opposite to that, a promise can send its notification only once. So you have to use more promise and future pairs to get the functionality of a condition variable. But if you use the condition variable only for one synchronization, the condition variable is a lot more challenging to use correctly. So a promise and future pair need no shared variable and, therefore, no lock; they are not prone to <a href=\"https:\/\/www.modernescpp.com\/index.php\/condition-variables\">spurious <\/a>or <a href=\"https:\/\/www.modernescpp.com\/index.php\/condition-variables\">lost wakeups<\/a>. In addition to that, they can handle exceptions. <strong>So there are a lot of reasons to prefer tasks to condition variables.<\/strong><\/p>\n<\/p>\n<p>How can I use tasks to synchronize threads?<\/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<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ promiseFutureSynchronize.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;future&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;utility&gt;<\/span>\r\n\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(std::future&lt;<span style=\"color: #2b91af;\">void<\/span>&gt;&amp;&amp; fut){\r\n\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Worker: Waiting for work.\"<\/span> &lt;&lt; std::endl;\r\n    fut.wait();\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\r\n<span style=\"color: #2b91af;\">void<\/span> setDataReady(std::promise&lt;<span style=\"color: #2b91af;\">void<\/span>&gt;&amp;&amp; prom){\r\n\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Sender: Data is ready.\"<\/span>  &lt;&lt; std::endl;\r\n    prom.set_value();\r\n\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::promise&lt;<span style=\"color: #2b91af;\">void<\/span>&gt; sendReady;\r\n  <span style=\"color: #0000ff;\">auto<\/span> fut= sendReady.get_future();\r\n\r\n  std::<span style=\"color: #0000ff;\">thread<\/span> t1(waitingForWork,std::move(fut));\r\n  std::<span style=\"color: #0000ff;\">thread<\/span> t2(setDataReady,std::move(sendReady));\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>Quite easy.<\/p>\n<p>With the help of the promise <span style=\"font-family: courier new,courier;\">sendReady<\/span> (line 32), I get the future <span style=\"font-family: courier new,courier;\">fut<\/span> (line 34). The promise signalizes, in this case by his return value<span style=\"font-family: courier new,courier;\"> void (std::promise&lt;void&gt; sendReady)<\/span>, that it can only send notifications. Both communications endpoints are moved into the threads <span style=\"font-family: courier new,courier;\">t1<\/span> respectively <span style=\"font-family: courier new,courier;\">t2<\/span> (lines 35 and 36). The future is waiting with its call <span style=\"font-family: courier new,courier;\">fut.wait()<\/span> (line 15) for the notification of the promise: <span style=\"font-family: courier new,courier;\">prom.set_value()<\/span> (line 24).<\/p>\n<p>Also, the structure as the program&#8217;s output matches the program in den post about the <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/condition-variable\">condition variable<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4780\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/promiseFutureSynchronize.png\" alt=\"promiseFutureSynchronize\" width=\"579\" height=\"227\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/promiseFutureSynchronize.png 579w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/promiseFutureSynchronize-300x118.png 300w\" sizes=\"auto, (max-width: 579px) 100vw, 579px\" \/><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>So that was the overview of the multithreading interface. Now it&#8217;s time to have a deeper look into multithreading in C++.&nbsp;Although most programmers will and should never use the features of the C++ memory model, it gives you a deeper insight into the challenges of multithreading programming. The <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-memory-model\">next post<\/a> starts with an overview of the C++ memory model. &nbsp;(<strong>Proofreader Alexey Elymanov<\/strong>)<\/p>\n<p>&nbsp;<\/p>\n<dl>\n<dt>\n<p>&nbsp;<\/p>\n<\/dt>\n<\/dl>\n<p>&nbsp;<\/p>\n<\/p>\n<p><span id=\"transmark\"><\/span>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In case you use promise and future to synchronize threads, they have much in common with condition variables. But most of the time, tasks are the better choice.<\/p>\n","protected":false},"author":21,"featured_media":4779,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[366],"tags":[451,446],"class_list":["post-4781","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-multithreading","tag-condition-variables","tag-tasks"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4781","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=4781"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4781\/revisions"}],"predecessor-version":[{"id":6973,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4781\/revisions\/6973"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/4779"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=4781"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=4781"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=4781"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}