<p>The problem is that your flags are ordinary <code>bool</code> variables, which results in a data race and therefore UB. That basically means that all bets are off about how your program behaves! For example, the compiler could hoist the load in the while-loop, effectively transforming the loop into an infinite loop. But infinite loops without side effects are also UB, so the compiler is well in its right to remove the loop entirely!</p>
<p>But even if the compiler does not perform these optimizations, the code still does not guarantee mutual exclusion, because the flag operations are not sequentially consistent. Essentially what can happen is that both threads store <code>true</code> in their respective flag, but it is not guaranteed that this updated value is visible to the other thread. So it can happen that the subsequent load operations in the while-loop still return false <em>for both threads</em>.</p>
<p>To get the desired behavior, the operations on the flags need to be <em>sequentially consistent</em>, which means that all such operations have a <em>single total order</em>. To achieve that you have to define your flags as <code>std::atomic&lt;bool&gt;</code>. All operations on atomics are sequentially consistent by default (unless specified otherwise).</p>
<p>However, since this is the third attempt by Dekker and not the final (correct) version, it does provide mutual exclusion (under a sequentially consistent memory model), but is prone to deadlocks!</p>
<p>For more details you should familiarize yourself with the C++ memory model. I can recommend the paper <a href="https://arxiv.org/abs/1803.04432" rel="nofollow noreferrer">Memory Models for C/C++ Programmers</a> which I have co-authored.</p>
Dekker Mutual-Exclusion
<p>I'm studying the operating system and the program that Dekker wrote for his third attempt to Mutual Exclusion
I wrote my code in C ++ in Visual Studio, the code is below, but I wonder how these two threads are still in the critical area at the same time?
The output of the program is below</p>
<pre><code>#include&lt;iostream&gt;
#include&lt;conio.h&gt;
#include&lt;thread&gt;
using namespace std;

bool flag0 = false;
bool flag1 = false;

void p1()
{
    flag0 = true;
    while (flag1);
    for (int i = 1; i &lt;= 10; i++)
        cout &lt;&lt; &quot;p1 : &quot; &lt;&lt; i &lt;&lt; endl;
    flag0 = false;

}

void p2()
{
    flag1 = true;
    while (flag0);
    for (int i = -1; i &gt;= -10; i--)
        cout &lt;&lt; &quot;p2 : &quot; &lt;&lt; i &lt;&lt; endl;
    flag1 = false;
}

int main()
{

    thread t1(p1);
    thread t2(p2);


    t1.join();
    t2.join();

    _getch();
    return 0;
}
</code></pre>
<p>Output:</p>
<pre><code>p1 : p2 : -11

p2 : p1 : 2
p1 : 3
p1 : 4
p1 : 5
p1 : 6
-2
p2 : -3
p2 : -4
p2 : -5
p2 : -6
p2 : -7
p2 : -8
p2 : -9
p2 : p1 : -107
p1 : 8
p1 : 9
p1 : 10
</code></pre>