{"id":6275,"date":"2022-01-07T11:55:17","date_gmt":"2022-01-07T11:55:17","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/dining-philiosophers-problem-i\/"},"modified":"2022-01-07T11:55:17","modified_gmt":"2022-01-07T11:55:17","slug":"dining-philiosophers-problem-i","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/dining-philiosophers-problem-i\/","title":{"rendered":"Dining Philosophers Problem I"},"content":{"rendered":"<hr \/>\n<p>At Christmas time, I had a few nice discussions with<strong> Andre Adrian<\/strong>. He solved the classical dining philosopher&#8217;s problem in various ways using modern C++. I convinced him to write an article about this classic synchronization issue, and I&#8217;m happy to publish it in three consecutive posts.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p><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>&nbsp;<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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>&nbsp;<\/p>\n<div>\n<h2>Dining philosophers in C++ by Andre Adrian<\/h2>\n<div>\n<p>Edsger W. Dijkstra described the dining philosophers&#8217; problem. &#8220;Five philosophers, numbered from 0 through 4 are living in a house where the table laid for them, each philosopher having his place at the table: Their only problem -besides those of philosophy- is that the dish served is a very difficult kind of spaghetti, that has to be eaten with two forks. There are two forks next to each plate, so that presents no difficulty: as a consequence, however, no two neighbors may be eating simultaneously.&#8221; [ref 1971; Dijkstra; EWD310 Hierarchical Ordering of Sequential Processes; <a href=\"https:\/\/www.cs.utexas.edu\/users\/EWD\/transcriptions\/EWD03xx\/EWD310.html\">https:\/\/www.cs.utexas.edu\/users\/EWD\/transcriptions\/EWD03xx\/EWD310.html<\/a>]<\/p>\n<div>&nbsp;<\/div>\n<div>\n<div>\n<p>We use the following problem description: 4 philosophers live a simple life. Every philosopher performs the same routine: he thinks for some random duration, gets his first fork, gets his second fork, eats for some random duration, puts down the forks, and starts thinking again. To make the problem interesting, the 4 philosophers have only 4 forks. Philosopher number 1 has to take forks number 1 and 2 for eating. Philosopher 2 needs forks 2 and 3, and so on, up to philosopher 4, who needs forks 4 and 1 for eating. After eating, the philosopher puts the forks back on the table.<\/p>\n<\/p>\n<h2>Multiple Resource Use<\/h2>\n<p>&nbsp;From problem description to programming, we translate philosophers to threads and forks to resources. In our first program &#8211; <code>dp_1.cpp<\/code> &#8211; we create 4 &#8220;philosopher&#8221; threads and 4 &#8220;fork&#8221; resource integers.<\/p>\n<\/div>\n<\/div>\n<div>&nbsp;<\/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<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\r\n46\r\n47\r\n48\r\n49\r\n50\r\n51\r\n52\r\n53\r\n54\r\n55<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ dp_1.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\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>(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;<\/span> m) {\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>(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&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, <span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;<\/span> ma, <span style=\"color: #007788; font-weight: bold;\">int<\/span><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_1<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n  srand(time(nullptr));\r\n\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/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>, m4, m1);});\r\n\r\n  t1.join();\r\n  t2.join();\r\n  t3.join();\r\n  t4.join();\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<div>\n<p>&nbsp;<\/p>\n<p>The <code>main() function<\/code> establishes random numbers in line 42. We set the random number generator seed value to the number of seconds since 1st January 1970. We define our fork resources in line 44. Then we start four threads beginning in line 46. To avoid premature thread termination, we join the threads beginning in line 51. The thread function<code> phil()<\/code> has a forever loop. The <code>while(true)<\/code> statement is always <code>true<\/code>, therefore the thread will never terminate. The problem description says, &#8220;he thinks for some random duration&#8221;. First, we calculate a random duration with the function <code>myrand(<\/code>), see line 20 and line 6. The function <code>myrand()<\/code> produces a pseudo-random return value in the range of [min, max). For program trace, we log the philosopher&#8217;s number, his current state of &#8220;he thinks,&#8221; and the duration to the console. The <code>sleep_for()<\/code> statement lets the scheduler put the thread for the duration into the waiting state. In a &#8220;real&#8221; program application, source code uses up time instead of <code>sleep_for()<\/code>.After the philosopher&#8217;s thread thinking time ends, he &#8220;gets his first fork&#8221;. See line 24. We use a function<code> lock()<\/code> to perform the &#8220;gets fork&#8221; thing. Currently, the function<code> lock()<\/code> is very simple because we don&#8217;t know better. We just set the fork resource to the value 1. See line 10. After the philosopher thread obtained his first fork, he proudly announces the new state with a.&#8221;<code>got ma<\/code>&#8221; console output. Now the thread &#8220;gets his second fork&#8221;. See line 28. The corresponding console output is &#8220;<code>got mb<\/code>&#8220;. The next state is &#8220;<code>he eats<\/code>&#8220;. Again, we determine the duration, produce a console output, and occupy the thread with a<code> sleep_for()<\/code>. See line 31. After the state.&#8221;<code>he eats<\/code>&#8221; the philosopher puts down his forks. See lines 35 and 14. The<code> unlock()<\/code> function is again really simple and sets the resource back to 0.<\/p>\n<p>Please compile the program without compiler optimization. We will see the reason later. The console output of our program looks promising:<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6269\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_1.png\" alt=\"dp 1\" width=\"400\" height=\"253\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_1.png 659w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_1-300x189.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<\/div>\n<div>\n<p>Have we already solved the dining philosophers&#8217; problem? Well, the program output is not detailed enough to answer this question.<\/p>\n<h2>Multiple Resource Use with Logging<\/h2>\n<p>We should add some more logging. Currently, the function<code> lock()<\/code> does not check if the fork is available before the resource is used. The improved version of <code>lock()<\/code> in program <code>dp_2.cpp<\/code> is:<\/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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">lock<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;<\/span> m) {\r\n  <span style=\"color: #006699; font-weight: bold;\">if<\/span> (m) {\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\\t\\t<\/span><span style=\"color: #cc3300;\">ERROR lock<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n  }\r\n  m<span style=\"color: #555555;\">=<\/span><span style=\"color: #ff6600;\">1<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div>\n<div>Program version 2 produces the following output:<\/div>\n<div>&nbsp;<\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6270\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_2.png\" alt=\"dp 2\" width=\"400\" height=\"253\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_2.png 659w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_2-300x189.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/div>\n<p>&nbsp;<\/p>\n<\/div>\n<div>\n<p>We see &#8220;<code>ERROR lock<\/code>&#8221; console output. This output tells us that two philosophers use the same resource simultaneously. What can we do?<\/p>\n<h2>Erroneous Busy Waiting without Resource Hierarchy<\/h2>\n<p>We can change the if statement in<code> lock()<\/code> into a while statement. This while statement produces a spinlock. A spinlock is a fancy word for busy waiting. While the fork resource is in use, the thread is busy waiting for a change from the state in use to the state available. At this very moment, we set the fork resource again to state in use. In the program, <code>dp_3.cpp<\/code> we have:<\/p>\n<p>&nbsp;<\/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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">lock<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&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<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div>\n<div>Please believe that this little change is still not a CORRECT solution for the dining philosophers&#8217; problem. We no longer have the wrong resource usage. But we have another problem. See program version 3 output:<\/div>\n<p>&nbsp;<\/p>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6271\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_3.png\" alt=\"dp 3\" width=\"400\" height=\"253\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_3.png 659w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_3-300x189.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/div>\n<div>\n<div>\n<p>&nbsp;<\/p>\n<p>Every philosopher thread takes his first fork resource and then can not take the second fork. What can we do? Andrew S. Tanenbaum wrote, &#8220;Another way to avoid the circular wait is to provide a global numbering of all the resources. The rule is this: processes can request resources whenever they want to, but all requests must be made in numerical order.&#8221; [ref 2006; Tanenbaum; Operating Systems. Design and Implementation, 3rd edition; chapter 3.3.5]<\/p>\n<h2>Erroneous Busy Waiting with Resource Hierarchy<\/h2>\n<p>This solution is known as resource hierarchy or partial ordering. For the dining philosopher&#8217;s problem, partial ordering is easy. The first fork taken has to be the fork with the lower number. For philosophers 1 to 3, the resources are taken in the correct order. Only philosopher thread 4 needs a change for correct partial ordering. First, get fork resource 1, then get fork resource 4. See the main program in the file<code> dp_4.cpp<\/code>:<\/p>\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%;\"><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_4<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n  srand(time(nullptr));\r\n\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/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<div>\n<div>Program version 4 output looks fine:<\/div>\n<div>&nbsp;<\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6272\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_4.png\" alt=\"dp 4\" width=\"400\" height=\"253\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_4.png 659w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_4-300x189.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/div>\n<div>\n<div>\n<div>&nbsp;<\/div>\n<p>Now there is no longer wrong resource usage nor do we have a deadlock. We get brave and use compiler optimization. We want to have a good program that executes fast! This is program version 4 output with compiler optimization:<\/p>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6273\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_4opt.png\" alt=\"dp 4opt\" width=\"400\" height=\"253\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_4opt.png 659w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_4opt-300x189.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div>\n<div>&nbsp;<\/div>\n<p>It is always the same philosopher thread that eats. Is it possible that the setting of compiler optimization can change the behavior of a program? Yes, it is possible. The philosopher threads read from memory the value of fork resource. The compiler optimization optimizes some of these memory reads away. Everything has a price!<\/p>\n<h2>Still Erroneous Busy Waiting with Resource Hierarchy<\/h2>\n<p>The programming language C++ has the atomic template to define an atomic type. The behavior is well-defined if one thread writes to an atomic object while another reads from it. In the file <code>dp_5.cpp<\/code> we use <code>atomic&lt;int&gt;<\/code> for the fork resources. See lines 11, 17, 21, and 47. We include<code> &lt;atomic&gt;<\/code> in line 5<code>:<\/code><\/p>\n<p>&nbsp;<\/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_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 version 5 output is:<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6274\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_5.png\" alt=\"dp 5\" width=\"400\" height=\"253\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_5.png 659w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/01\/dp_5-300x189.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<div>\n<div>This output looks great. Now we have reached the limits of our testing methodology. There is still a<em> tiny chance for misbehavior<\/em>. The two operations &#8220;is a resource available&#8221; and &#8220;mark resource as in use&#8221; in the lock() 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.<\/div>\n<div>&nbsp;<\/div>\n<h2>What&#8217;s next?<\/h2>\n<p>The next installment of this dining philosopher problem solves the<em> tiny chance of misbehavior<\/em>. So far, none of the programs have been correct.<\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>At Christmas time, I had a few nice discussions with Andre Adrian. He solved the classical dining philosopher&#8217;s problem in various ways using modern C++. I convinced him to write an article about this classic synchronization issue, and I&#8217;m happy to publish it in three consecutive posts.<\/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":[],"class_list":["post-6275","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-multithreading-application"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6275","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=6275"}],"version-history":[{"count":0,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6275\/revisions"}],"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=6275"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6275"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6275"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}