{"id":6278,"date":"2022-01-08T11:50:06","date_gmt":"2022-01-08T11:50:06","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/dining-philiosophers-problem-ii\/"},"modified":"2023-06-26T09:17:44","modified_gmt":"2023-06-26T09:17:44","slug":"dining-philiosophers-problem-ii","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/dining-philiosophers-problem-ii\/","title":{"rendered":"Dining Philosophers Problem II"},"content":{"rendered":"<p>In the last post &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/dining-philiosophers-problem-i\">Dining Philosophers Problem I<\/a>&#8220;,<strong> Andre Adrian<\/strong> started his analysis of the classical dining philosophers&#8217; problem. Today, he uses atomics, mutexes, and locks.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6268\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/An_illustration_of_the_dining_philosophers_problem.png\" alt=\"An illustration of the dining philosophers problem\" width=\"400\" height=\"415\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/An_illustration_of_the_dining_philosophers_problem.png 800w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/An_illustration_of_the_dining_philosophers_problem-289x300.png 289w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/An_illustration_of_the_dining_philosophers_problem-768x797.png 768w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p style=\"text-align: center;\">&nbsp;<\/p>\n<p style=\"text-align: center;\">By Benjamin D. Esham \/ Wikimedia Commons, CC BY-SA 3.0, <a href=\"https:\/\/commons.wikimedia.org\/w\/index.php?curid=56559\">https:\/\/commons.wikimedia.org\/w\/index.php?curid=56559<\/a><\/p>\n<p>Let me give you a quick reminder about where Andre&#8217;s analysis ended last time.<\/p>\n<h2>Still Erroneous Busy Waiting with Resource Hierarchy<\/h2>\n<div>&nbsp;<\/div>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ dp_5.cpp<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;chrono&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;atomic&gt;<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">myrand<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> min, <span style=\"color: #007788; font-weight: bold;\">int<\/span> max) {\r\n  <span style=\"color: #006699; font-weight: bold;\">return<\/span> rand()<span style=\"color: #555555;\">%<\/span>(max<span style=\"color: #555555;\">-<\/span>min)<span style=\"color: #555555;\">+<\/span>min;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">lock<\/span>(std<span style=\"color: #555555;\">::<\/span>atomic<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;&amp;<\/span> m) {\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span> (m)\r\n    ; <span style=\"color: #0099ff; font-style: italic;\">\/\/ busy waiting<\/span>\r\n  m<span style=\"color: #555555;\">=<\/span><span style=\"color: #ff6600;\">1<\/span>;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">unlock<\/span>(std<span style=\"color: #555555;\">::<\/span>atomic<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;&amp;<\/span> m) {\r\n  m<span style=\"color: #555555;\">=<\/span><span style=\"color: #ff6600;\">0<\/span>;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">phil<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> ph, std<span style=\"color: #555555;\">::<\/span>atomic<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;&amp;<\/span> ma, std<span style=\"color: #555555;\">::<\/span>atomic<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;&amp;<\/span> mb) {\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span>(<span style=\"color: #336666;\">true<\/span>) {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" thinks \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n\r\n    lock(ma);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got ma<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(<span style=\"color: #ff6600;\">1000<\/span>));\r\n\r\n    lock(mb);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got mb<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n\r\n    duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" eats \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n\r\n    unlock(mb);\r\n    unlock(ma);\r\n  }\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n  std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"dp_5<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n  srand(time(nullptr));\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>atomic<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> m1{<span style=\"color: #ff6600;\">0<\/span>}, m2{<span style=\"color: #ff6600;\">0<\/span>}, m3{<span style=\"color: #ff6600;\">0<\/span>}, m4{<span style=\"color: #ff6600;\">0<\/span>};\r\n\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t1([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">1<\/span>, m1, m2);});\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t2([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">2<\/span>, m2, m3);});\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t3([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">3<\/span>, m3, m4);});\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t4([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">4<\/span>, m1, m4);});\r\n\r\n  t1.join();\r\n  t2.join();\r\n  t3.join();\r\n  t4.join();\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The program looks fine but has a<em> tiny chance of misbehavior<\/em>. The two operations &#8220;is a resource available&#8221; and &#8220;mark resource as in use&#8221; in the<code> lock()<\/code> function is atomic, but they are still two operations. Between these two operations, the scheduler can place a thread switch. And this thread switches at this most inconvenient time can produce hard-to-find bugs in the program.<\/p>\n<\/p>\n<h2>Optimized Busy Waiting with Resource Hierarchy<\/h2>\n<div>\n<p>Thankfully all current computers have an atomic operation &#8220;test the resource, and if the test is positive, mark resource as in use&#8221;. In the programming language C++, the <code>atomic_flag<\/code> type makes this special &#8220;test and set&#8221; operation available. The file <code>dp_6.cpp<\/code> is the first correct solution for the dining philosophers problem:<\/p>\n<\/div>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ dp_6.cpp<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;chrono&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;atomic&gt;<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">myrand<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> min, <span style=\"color: #007788; font-weight: bold;\">int<\/span> max) {\r\n  <span style=\"color: #006699; font-weight: bold;\">return<\/span> rand()<span style=\"color: #555555;\">%<\/span>(max<span style=\"color: #555555;\">-<\/span>min)<span style=\"color: #555555;\">+<\/span>min;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">lock<\/span>(std<span style=\"color: #555555;\">::<\/span>atomic_flag<span style=\"color: #555555;\">&amp;<\/span> m) {\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span> (m.test_and_set())\r\n    ; <span style=\"color: #0099ff; font-style: italic;\">\/\/ busy waiting<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">unlock<\/span>(std<span style=\"color: #555555;\">::<\/span>atomic_flag<span style=\"color: #555555;\">&amp;<\/span> m) {\r\n  m.clear();\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">phil<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> ph, std<span style=\"color: #555555;\">::<\/span>atomic_flag<span style=\"color: #555555;\">&amp;<\/span> ma, std<span style=\"color: #555555;\">::<\/span>atomic_flag<span style=\"color: #555555;\">&amp;<\/span> mb) {\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span>(<span style=\"color: #336666;\">true<\/span>) {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" thinks \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n\r\n    lock(ma);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got ma<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(<span style=\"color: #ff6600;\">1000<\/span>));\r\n\r\n    lock(mb);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got mb<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n\r\n    duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" eats \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n\r\n    unlock(mb);\r\n    unlock(ma);\r\n  }\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n  std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"dp_6<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n  srand(time(nullptr));\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>atomic_flag m1, m2, m3, m4;\r\n  unlock(m1);\r\n  unlock(m2);\r\n  unlock(m3);\r\n  unlock(m4);\r\n\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t1([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">1<\/span>, m1, m2);});\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t2([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">2<\/span>, m2, m3);});\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t3([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">3<\/span>, m3, m4);});\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t4([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">4<\/span>, m1, m4);});\r\n\r\n  t1.join();\r\n  t2.join();\r\n  t3.join();\r\n  t4.join();\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div>\n<div>The program version 6 output is similar to the last output. The dining philosophers&#8217; problem is good-natured. One resource is only shared between two threads. The<code> atomic_fla<\/code>g spinlock is needed if several threads want to get the same resource.<\/div>\n<div>&nbsp;<\/div>\n<div>\n<h2>Good low CPU load Busy Waiting with Resource Hierarchy<\/h2>\n<\/div>\n<div>&nbsp;<\/div>\n<div>The spinlock disadvantage is the busy waiting. The while loop<code> lock()<\/code> is a waste of CPU resources. A remedy to this problem is putting a function in this while loop&#8217;s body. The<code> sleep_for()<\/code> function performs waiting in the scheduler. This waiting is much better than waiting in the application. As always, there is a price. The <code>sleep_for()<\/code> slows down the program&#8217;s progress. The file<code> dp_7.cpp<\/code> is the second correct solution:<\/div>\n<div>&nbsp;<\/div>\n<\/div>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ dp_7.cpp<\/span><br \/>void<\/span> <span style=\"color: #cc00ff;\">lock<\/span>(std<span style=\"color: #555555;\">::<\/span>atomic_flag<span style=\"color: #555555;\">&amp;<\/span> m) {\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span> (m.test_and_set())\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(<span style=\"color: #ff6600;\">8<\/span>));\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div>\n<div>Note: a <code>std::this_thread::yield()<\/code> instead of the <code>sleep_for()<\/code> does not reduce CPU load on the author&#8217;s computer. The impact of<code> yield()<\/code> is implementation-dependent.<\/div>\n<div>\n<h2>std::mutex with Resource Hierarchy<\/h2>\n<\/div>\n<div>&nbsp;<\/div>\n<div>To altogether avoid busy waiting, we need more help from the scheduler. If every thread tells the scheduler the resource state, the scheduler can put a &#8220;wait for a resource&#8221; thread into the &#8220;waiting&#8221; state. After the scheduler gets &#8220;resource is available&#8221; information, the waiting thread state changes to ready. The thread to scheduler information exchange is expensive. Because of this, C++ offers both spinlock and mutex. Spinlock is waiting in the thread, and mutex is waiting in the scheduler.<\/div>\n<div>File <code>dp_8.cpp<\/code> shows the mutex solution. Please note the <code>#include &lt;mutex&gt;<\/code> :<\/div>\n<div>&nbsp;<\/div>\n<\/div>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ dp_8.cpp<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;chrono&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;mutex&gt;<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">myrand<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> min, <span style=\"color: #007788; font-weight: bold;\">int<\/span> max) {\r\n  <span style=\"color: #006699; font-weight: bold;\">return<\/span> rand()<span style=\"color: #555555;\">%<\/span>(max<span style=\"color: #555555;\">-<\/span>min)<span style=\"color: #555555;\">+<\/span>min;\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">phil<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> ph, std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&amp;<\/span> ma, std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&amp;<\/span> mb) {\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span>(<span style=\"color: #336666;\">true<\/span>) {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" thinks \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n\r\n    ma.lock();\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got ma<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(<span style=\"color: #ff6600;\">1000<\/span>));\r\n\r\n    mb.lock();\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got mb<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n\r\n    duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" eats \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n    mb.unlock(); <span style=\"color: #0099ff; font-style: italic;\">\/\/ (9)<\/span>\r\n    ma.unlock();\r\n  }\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n  std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"dp_8<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n  srand(time(nullptr));\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>mutex m1, m2, m3, m4;\r\n\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t1([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">1<\/span>, m1, m2);});\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t2([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">2<\/span>, m2, m3);});\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t3([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">3<\/span>, m3, m4);});\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t4([<span style=\"color: #555555;\">&amp;<\/span>] {phil(<span style=\"color: #ff6600;\">4<\/span>, m1, m4);});\r\n\r\n  t1.join();\r\n  t2.join();\r\n  t3.join();\r\n  t4.join();\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div>\n<div>Program version 8 is correct and uses very few CPU resources. C++ offers a wrapper to mutex to make life easier for programmers.<\/div>\n<h2><code>std::lock_guard<\/code> with Resource Hierarchy<\/h2>\n<div>&nbsp;<\/div>\n<div>Using the <code>lock_guard<\/code> template, we put only the mutex into the lock. The mutex member function <code>lock<\/code> is automatically called in the locks constructor and <code>unlock<\/code> its destructor at the end of the scope. <code>unlock<\/code> is also called if an exception is thrown.<\/div>\n<div>\n<p>&nbsp;<\/p>\n<p>The convenient version is<code> dp_9.cpp<\/code>:<\/p>\n<\/div>\n<div>&nbsp;<\/div>\n<\/div>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007788;\"><span style=\"color: #000000;\">\/\/ dp_9.cpp<\/span><\/span><span style=\"color: #007788; font-weight: bold;\"><br \/><br \/>void<\/span> <span style=\"color: #cc00ff;\">phil<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> ph, std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&amp;<\/span> ma, std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&amp;<\/span> mb) {\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span>(<span style=\"color: #336666;\">true<\/span>) {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" thinks \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> ga(ma);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got ma<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(<span style=\"color: #ff6600;\">1000<\/span>));\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> gb(mb);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got mb<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n\r\n    duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" eats \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n  }\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div>\n<div>We get better and better. Program versions 8 and 9 are correct and are light on the CPU load. But look carefully at the program output:<\/div>\n<div>&nbsp;<\/div>\n<div>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6276\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_8.png\" alt=\"dp 8\" width=\"500\" height=\"316\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_8.png 659w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_8-300x189.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/div>\n<\/div>\n<div><\/p>\n<div>The program output is slightly garbled. Maybe you have seen this output distortion before. Nothing is wrong with the spinlock program versions 6 and 7 or the mutex programs 8 and 9.<\/div>\n<div>&nbsp;<\/div>\n<div>\n<h2><code>std::lock_guard<\/code> and Synchronized Output with Resource Hierarchy<\/h2>\n<\/div>\n<div>&nbsp;<\/div>\n<div>The console output itself is a resource. That is the reason for garbled output in multi-thread programs. The solution is to put a <code>lock_guard<\/code> around every console output. See <code>dp_10.cpp<\/code>:<\/div>\n<div>&nbsp;<\/div>\n<div>&nbsp;<\/div>\n<\/div>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">\/\/ dp_10.cpp<br \/><br \/>std<span style=\"color: #555555;\">::<\/span>mutex mo;\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">phil<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> ph, std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&amp;<\/span> ma, std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&amp;<\/span> mb) {\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span>(<span style=\"color: #336666;\">true<\/span>) {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    {\r\n      std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> g(mo);\r\n      std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" thinks \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    }\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> ga(ma);\r\n    {\r\n      std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> g(mo);\r\n      std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got ma<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    }\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(<span style=\"color: #ff6600;\">1000<\/span>));\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> gb(mb);\r\n    {\r\n      std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> g(mo);\r\n      std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got mb<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    }\r\n\r\n    duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    {\r\n      std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> g(mo);\r\n      std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" eats \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    }\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n  }\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div>\n<div>The global mutex <code>mo<\/code> controls the console output resource. Every <code>cout<\/code> statement is in its block, and the <code>lock_guard()<\/code> template ensures that console output is no longer garbled.<\/div>\n<div>\n<div>\n<h2><code>std::lock_guard<\/code> and Synchronized Output with Resource Hierarchy and a count<\/h2>\n<\/div>\n<\/div>\n<div>&nbsp;<\/div>\n<div>\n<div>\n<div>As a little bonus, I added<code> dp_11.cpp<\/code>. This program version counts the number of philosophers threads that are eating simultaneously. Because we have 4 forks, there should be times when 2 philosopher threads eat concurrently. Please note that you need again<code> #include &lt;atomic&gt;<\/code>. See <code>dp_11.cpp<\/code>:<\/div>\n<div>&nbsp;<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">\/\/ dp_11.cpp<br \/><br \/>std<span style=\"color: #555555;\">::<\/span>mutex mo;\r\nstd<span style=\"color: #555555;\">::<\/span>atomic<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> cnt <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">phil<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> ph, std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&amp;<\/span> ma, std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&amp;<\/span> mb) {\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span>(<span style=\"color: #336666;\">true<\/span>) {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    {\r\n      std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> g(mo);\r\n      std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" thinks \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    }\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> ga(ma);\r\n    {\r\n      std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> g(mo);\r\n      std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got ma<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    }\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(<span style=\"color: #ff6600;\">1000<\/span>));\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> gb(mb);\r\n    {\r\n      std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> g(mo);\r\n      std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" got mb<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    }\r\n\r\n    duration<span style=\"color: #555555;\">=<\/span>myrand(<span style=\"color: #ff6600;\">1000<\/span>, <span style=\"color: #ff6600;\">2000<\/span>);\r\n    <span style=\"color: #555555;\">++<\/span>cnt;\r\n    {\r\n      std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> g(mo);\r\n      std<span style=\"color: #555555;\">::<\/span>cout<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t\\t\\t<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>ph<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\" eats \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>duration<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"ms \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span>cnt<span style=\"color: #555555;\">&lt;&lt;<\/span><span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    }\r\n    std<span style=\"color: #555555;\">::<\/span>this_thread<span style=\"color: #555555;\">::<\/span>sleep_for(std<span style=\"color: #555555;\">::<\/span>chrono<span style=\"color: #555555;\">::<\/span>milliseconds(duration));\r\n    <span style=\"color: #555555;\">--<\/span>cnt;\r\n  }\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div>\n<div>The program version 11 output is:<\/div>\n<div>&nbsp;<\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6277\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_11.png\" alt=\"dp 11\" width=\"600\" height=\"379\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_11.png 659w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_11-300x189.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The addition is 1 or 2 at the end of the &#8220;eats&#8221; logging.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>In his next installment of the dining philosophers problem, Andre uses<code> std::unique_lock<\/code> (C++11), <code>std::scoped_lock<\/code> (C++17), and <code>std::semaphore<\/code> (C++20).<\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<div id=\"simple-translate\">\n<div>\n<div class=\"simple-translate-button isShow\" style=\"background-image: url('moz-extension:\/\/981aa874-2db4-44d3-a97f-b02a72476831\/icons\/512.png'); height: 22px; width: 22px; top: 145px; left: 15px;\">&nbsp;<\/div>\n<div class=\"simple-translate-panel\" style=\"width: 300px; height: 200px; top: 0px; left: 0px; font-size: 13px; background-color: #ffffff;\">\n<div class=\"simple-translate-result-wrapper\" style=\"overflow: hidden;\">\n<div class=\"simple-translate-move\" draggable=\"draggable\">&nbsp;<\/div>\n<div class=\"simple-translate-result-contents\">\n<p class=\"simple-translate-result\" dir=\"auto\" style=\"color: #000000;\">&nbsp;<\/p>\n<p class=\"simple-translate-candidate\" dir=\"auto\" style=\"color: #737373;\">&nbsp;<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In the last post &#8220;Dining Philosophers Problem I&#8220;, Andre Adrian started his analysis of the classical dining philosophers&#8217; problem. Today, he uses atomics, mutexes, and locks.<\/p>\n","protected":false},"author":21,"featured_media":6268,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[369],"tags":[434,432,430,433],"class_list":["post-6278","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-multithreading-application","tag-atomics","tag-dining-philosophers","tag-lock","tag-mutex"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6278","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=6278"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6278\/revisions"}],"predecessor-version":[{"id":6686,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6278\/revisions\/6686"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/6268"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6278"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6278"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6278"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}