{"id":5435,"date":"2018-05-04T05:30:38","date_gmt":"2018-05-04T05:30:38","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-use-tools-to-validate-your-concurrent-code\/"},"modified":"2023-06-26T11:51:26","modified_gmt":"2023-06-26T11:51:26","slug":"c-core-guidelines-use-tools-to-validate-your-concurrent-code","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-use-tools-to-validate-your-concurrent-code\/","title":{"rendered":"C++ Core Guidelines: Use Tools to Validate your Concurrent Code"},"content":{"rendered":"<p>Today, I&#8217;m happy to write about the probably most important C++ Core Guidelines for concurrency rule: Whenever feasible, use tools to validate your concurrent code. Not all, but many bugs&nbsp;can be detected with tools, and each fixed bug is a good bug. Here are two tools that gave me precious help in the last few years: <a href=\"https:\/\/github.com\/google\/sanitizers\/wiki\/ThreadSanitizerCppManual\">ThreadSanitizer<\/a> and <a href=\"http:\/\/svr-pes20-cppmem.cl.cam.ac.uk\/cppmem\/\">CppMem<\/a>.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5431\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/wrench-24261_640.png\" alt=\"wrench 24261 640\" width=\"500\" height=\"474\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/wrench-24261_640.png 640w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/wrench-24261_640-300x285.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>Here is the rule for today:<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rconc-tools\" style=\"color: #268bd2; text-decoration: underline;\">CP.9: Whenever feasible use tools to validate your concurrent code<\/a><\/h2>\n<p>This post is based on personal experience. On the one hand, a lot of my students in my multithreading classes wrote programs with data race; on the other hand, I implemented a lot of multithreading programs with bugs. How can I be sure? Because of the dynamic code analysis tool&nbsp;<a href=\"https:\/\/github.com\/google\/sanitizers\/wiki\/ThreadSanitizerCppManual\">ThreadSanitizer<\/a>&nbsp;and the static code analysis tool <a href=\"http:\/\/svr-pes20-cppmem.cl.cam.ac.uk\/cppmem\/\">CppMem<\/a>. The use cases for ThreadSanitizer and CppMem are different.<\/p>\n<p>ThreadSanitizer gives you the big picture and detects if the execution of your program has a data race. CppMem gives you a detailed insight into small pieces of code, most of the time including atomics. You will get the answer to the question: Which interleavings are possible according to the memory model?&nbsp;<\/p>\n<p>Let&#8217;s start with ThreadSanitizer.<\/p>\n<\/p>\n<h3>ThreadSanitizer<\/h3>\n<p>Here is the official introduction to <a href=\"https:\/\/github.com\/google\/sanitizers\/wiki\/ThreadSanitizerCppManual\">ThreadSanitizer<\/a>: &#8220;ThreadSanitizer (aka TSan) is a data race detector for C\/C++. Data races are one of the most common and hardest-to-debug types of bugs in concurrent systems. A data race occurs when two threads access the same variable concurrently, and at least one access is written.&nbsp;<a href=\"http:\/\/en.wikipedia.org\/wiki\/C%2B%2B11\" rel=\"nofollow\">C++11<\/a>&nbsp;standard officially bans data races as&nbsp;undefined behavior.&#8221;<\/p>\n<p>ThreadSanitizer is part of clang 3.2 and gcc&nbsp;4.8; it supports&nbsp;Linux x86_64, and is tested on Ubuntu 12.04. You have to compile and link against&nbsp;<span style=\"font-family: 'courier new', courier;\">-fsanitize=thread<\/span>, use at least optimization level <span style=\"font-family: 'courier new', courier;\">-O2<\/span> and the flag <span style=\"font-family: 'courier new', courier;\">-g<\/span>&nbsp;for producing debugging information: <span style=\"font-family: 'courier new', courier;\">-fsanitize=thread -O2 -g<\/span>.&nbsp;<\/p>\n<p>The runtime overhead is significant:&nbsp;&nbsp;the memory usage may increase by 5-10x and the execution time by 2-20x. But of course, you&nbsp;know the principal law of software development: <strong>First, your program should be correct than fast.<\/strong>&nbsp;<\/p>\n<h4>The ping-pong game<\/h4>\n<p>Now, let&#8217;s see ThreadSanitizer in action. Here is a typical exercise I often have given in my multithreading classes&nbsp;to condition variables:<\/p>\n<p>Write a small ping pong game.<\/p>\n<ul>\n<li>Two threads should alternatively set a bool value to <span style=\"font-family: 'courier new', courier;\">true<\/span> or fa<span style=\"font-family: 'courier new', courier;\">l<\/span>se. One thread sets the value to <span style=\"font-family: 'courier new', courier;\">true<\/span> and notifies the other thread.&nbsp;The other&nbsp;thread sets the value to <span style=\"font-family: 'courier new', courier;\">false<\/span> and notifies the original thread. That play should end after a fixed&nbsp;amount of iterations.&nbsp;<\/li>\n<\/ul>\n<p>And this is the typical&nbsp;implementation my students came up with.<\/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;\">\/\/ conditionVariablePingPong.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;condition_variable&gt;<\/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\r\n<span style=\"color: #007788; font-weight: bold;\">bool<\/span> dataReady<span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">false<\/span>;                                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>mutex mutex_;\r\nstd<span style=\"color: #555555;\">::<\/span>condition_variable condVar1;\r\nstd<span style=\"color: #555555;\">::<\/span>condition_variable condVar2;\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> counter<span style=\"color: #555555;\">=<\/span><span style=\"color: #ff6600;\">0<\/span>;\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> COUNTLIMIT<span style=\"color: #555555;\">=<\/span><span style=\"color: #ff6600;\">50<\/span>;\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">setTrue<\/span>(){                                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span>(counter <span style=\"color: #555555;\">&lt;=<\/span> COUNTLIMIT){                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (7)<\/span>\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>unique_lock<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> lck(mutex_);\r\n    condVar1.wait(lck, []{<span style=\"color: #006699; font-weight: bold;\">return<\/span> dataReady <span style=\"color: #555555;\">==<\/span> <span style=\"color: #336666;\">false<\/span>;});   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\r\n    dataReady<span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">true<\/span>;\r\n    <span style=\"color: #555555;\">++<\/span>counter;                                            <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> dataReady <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    condVar2.notify_one();                                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (6)<\/span>\r\n\r\n  }\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">setFalse<\/span>(){                                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n\r\n  <span style=\"color: #006699; font-weight: bold;\">while<\/span>(counter <span style=\"color: #555555;\">&lt;<\/span> COUNTLIMIT){                             <span style=\"color: #0099ff; font-style: italic;\">\/\/ (8)<\/span>\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>unique_lock<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> lck(mutex_);\r\n    condVar2.wait(lck, []{<span style=\"color: #006699; font-weight: bold;\">return<\/span> dataReady <span style=\"color: #555555;\">==<\/span> <span style=\"color: #336666;\">true<\/span>;});\r\n    dataReady<span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">false<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> dataReady <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    condVar1.notify_one();\r\n\r\n  }\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\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>boolalpha <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Begin: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> dataReady <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t1(setTrue);\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> t2(setFalse);\r\n\r\n  t1.join();\r\n  t2.join();\r\n  \r\n  dataReady<span style=\"color: #555555;\">=<\/span> <span style=\"color: #336666;\">false<\/span>;\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"End: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> dataReady <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Function <span style=\"font-family: courier\\ new, courier;\">setTrue<\/span> (1) sets the boolean value <span style=\"font-family: courier\\ new, courier;\">dataReady<\/span> (3) to <span style=\"font-family: courier\\ new, courier;\">true<\/span> and function <span style=\"font-family: courier\\ new, courier;\">setFalse<\/span> (2) sets it to <span style=\"font-family: courier\\ new, courier;\">false<\/span>.&nbsp; The play starts with <span style=\"font-family: courier\\ new, courier;\">setTrue<\/span>. The condition variable in the function waits for the notification and therefore checks first the boolean <span style=\"font-family: courier\\ new, courier;\">dataReady<\/span> (4). Afterward, the function increments the <span style=\"font-family: courier\\ new, courier;\">counter<\/span> (5) and notifies the other thread with the help of the condition variable <span style=\"font-family: courier\\ new, courier;\">condVar2<\/span> (6). The function <span style=\"font-family: courier\\ new, courier;\">setFalse<\/span> follows the same workflow. If <span style=\"font-family: 'courier new', courier;\">counter<\/span> becomes equal to <span style=\"font-family: courier\\ new, courier;\">COUNTLIMIT<\/span> (7), the game ends. Fine? NO!<\/p>\n<p>There is a data race on the counter. It is read (8) and written (5) and the same time. Thanks to ThreadSanitizer. Here is the proof.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5432\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/pingPongDataRace.png\" alt=\"pingPongDataRace\" width=\"700\" height=\"500\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/pingPongDataRace.png 1251w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/pingPongDataRace-300x214.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/pingPongDataRace-1024x732.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/pingPongDataRace-768x549.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;ThreadSanitzer detects data races during runtime, CppMem lets you analyze small code snippets.<\/p>\n<h3>CppMem&nbsp;<\/h3>\n<p>I will only provide a short overview of CppMem.<\/p>\n<p>The online tool, which you can also install on your CPP provides very precious services.<\/p>\n<ol>\n<li>CppMem validates small code snippets, typically including atomics.<\/li>\n<li>The very accurate analysis of CppMem gives you a deep insight into the C++ memory model.<\/li>\n<\/ol>\n<p>For deeper insight, I have already written a few posts to <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/cppmem\">CppMem<\/a>. For now, I will only refer to the first point and provide your with a 10000 feet view overview.<\/p>\n<h3>A Short Overview<\/h3>\n<p>My simplified overview uses the default configuration of the tool. This overview should give you the base for further experiments.<\/p>\n<p>I will refer to the red numbers in the following screenshot for simplicity reasons.&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5433\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/CppMemNumbers.PNG\" alt=\"CppMemNumbers\" width=\"700\" height=\"461\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/CppMemNumbers.PNG 1248w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/CppMemNumbers-300x198.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/CppMemNumbers-1024x674.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/CppMemNumbers-768x506.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<ol>\n<li><strong>Model<\/strong>\n<ul>\n<li>Specifies the C++ memory model. <em>preferred<\/em> is the C++ memory model.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Program<\/strong>\n<ul>\n<li>Is the executable program in C or C++-like syntax?<\/li>\n<li>CppMem offers a bunch of typical atomic workflow. To get the details of these programs, read the well-written article <a href=\"http:\/\/www.cl.cam.ac.uk\/~pes20\/cpp\/popl085ap-sewell.pdf\">Mathematizing C++ Concurrency<\/a>. Of course, you can also use your own code.<\/li>\n<li>CppMem is about multithreading, so there are a few simplifications\n<ul>\n<li>You can easily define two threads by the symbols <span style=\"font-family: courier new,courier;\">{{{&nbsp; &#8230; ||| &#8230; }}}<\/span>.&nbsp;The three dots (&#8230;) stand for the work package of the thread.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li><strong>Display Relations<\/strong>\n<ul>\n<li>Describes the relations between the read, write, and read-write modifications on atomic operations, fences, and locks.&nbsp;<\/li>\n<li>If the relation is enabled, it will be displayed in the annotated graph (see point 6).\n<ul>\n<li>Here are a few relations:\n<ul>\n<li><strong>sb<\/strong>: sequenced-before<\/li>\n<li><strong>rf:<\/strong> read from<\/li>\n<li><strong>mo<\/strong>: modification order<\/li>\n<li><strong>sc<\/strong>: sequentially consistent<\/li>\n<li><strong>lo<\/strong>: lock order<\/li>\n<li><strong>sw:<\/strong> synchronizes-with<\/li>\n<li><strong>dob<\/strong>: dependency-ordered-before<\/li>\n<li><strong>data_races<\/strong><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li><strong>Display Layout<\/strong>\n<ul>\n<li>You can choose with this switch which <a href=\"https:\/\/sourceforge.net\/projects\/doxygraph\/\">Doxygraph<\/a> graph is used.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Choose the Executions<\/strong>\n<ul>\n<li>Switch between the various consistent executions.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Annotated Graph<\/strong>\n<ul>\n<li>Displays the annotated graph.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Now, let&#8217;s try it out.<\/p>\n<h3>A Data Race<\/h3>\n<p>First, my program with a data race on <span style=\"font-family: courier\\ new, courier;\">x (1)<\/span>. The atomic <span style=\"font-family: courier\\ new, courier;\">y i<\/span>s fine. Independent of the applied <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/atomic\/memory_order\">memory-order<\/a>, the operations on<span style=\"font-family: courier\\ new, courier;\"> y<\/span> are at least atomic.<\/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;\">\/\/ dataRaceOnX.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;atomic&gt;<\/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\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\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> y{<span style=\"color: #ff6600;\">0<\/span>};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">writing<\/span>(){  \r\n  x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2000<\/span>;                                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n  y.store(<span style=\"color: #ff6600;\">11<\/span>, std<span style=\"color: #555555;\">::<\/span>memory_order_release);                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">reading<\/span>(){  \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> y.load(std<span style=\"color: #555555;\">::<\/span>memory_order_acquire) <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>; <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> x <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> thread1(writing);\r\n    std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span> thread2(reading);\r\n\r\n    thread1.join();\r\n    thread2.join();\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Here is the equivalent program in the simplified CppMem syntax.<\/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;\">\/\/ dataRaceOnXCppMem.txt<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n  atomic_int y <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n  \r\n  {{{ \r\n    {\r\n      x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2000<\/span>;\r\n      y.store(<span style=\"color: #ff6600;\">11<\/span>, memory_order_release);\r\n    }\r\n  <span style=\"color: #555555;\">|||<\/span> \r\n    {\r\n      y.load(memory_order_acquire);\r\n      x;\r\n    }\r\n  }}}\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>CppMem shows it immediately. The first consistent execution has a data race on x.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5434\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/DataRaceOnX.png\" alt=\"DataRaceOnX\" width=\"400\" height=\"232\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/DataRaceOnX.png 396w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/05\/DataRaceOnX-300x174.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>You can observe the data race in the graph. It is the yellow edge (dr) between the write (<span style=\"font-family: courier\\ new, courier;\">x=2000<\/span>) and the read operation (<span style=\"font-family: courier\\ new, courier;\">x=0<\/span>).<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Of course, there are many more rules to concurrency in the C++ Core Guidelines. The <a href=\"https:\/\/goo.gl\/GsFWPd\">next post <\/a>will be about locks and mutexes.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today, I&#8217;m happy to write about the probably most important C++ Core Guidelines for concurrency rule: Whenever feasible, use tools to validate your concurrent code. Not all, but many bugs&nbsp;can be detected with tools, and each fixed bug is a good bug. Here are two tools that gave me precious help in the last few [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":5431,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[486,485],"class_list":["post-5435","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-cppmem","tag-threadsanitizer"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5435","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=5435"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5435\/revisions"}],"predecessor-version":[{"id":6828,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5435\/revisions\/6828"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5431"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5435"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5435"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5435"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}