Dekker’s Algorithm was the first correct solution to the critical section problem for two processes. It is significant in the history of operating systems because:
- It avoids the drawbacks of naïve alternation (strict turn-taking).
- It uses only shared memory (Boolean flags and a turn variable).
- It ensures mutual exclusion, progress, and bounded waiting.
A process is generally represented as :
do {
//entry section
critical section
//exit section
remainder section
} while (TRUE);
The solution to the critical section problem must ensure the following three conditions:
- Mutual Exclusion
- Progress
- Bounded Waiting
Algorithm: It requires both an array of Boolean values and an integer variable:
var flag: array [0..1] of boolean;
turn: 0..1;
repeat
flag[i] := true;
while flag[j] do
if turn = j then
begin
flag[i] := false;
while turn = j do no-op;
flag[i] := true;
end;
critical section
turn := j;
flag[i] := false;
remainder section
until false;
Evolution of Dekker’s Algorithm
Dekker’s Algorithm was developed in five versions, each improving upon the previous one. Let’s analyze them:
1. First Version of Dekker's Solution
The idea is to use a common or shared thread number between processes and stop the other process from entering its critical section if the shared thread indicates the former one already running.
- Idea: Use a shared variable
turnto decide whose turn it is. - Execution: A process can enter only when
turnmatches its ID. - Problem: If one process stops entering, the other may wait forever → No progress guarantee.
Main()
{
int thread_number = 1;
startThreads();
}
Thread1()
{
do {
while (threadnumber == 2);
threadnumber = 2;
} while (completed == false)
}
Thread2()
{
do {
while (threadnumber == 1) ;
threadnumber = 1;
} while (completed == false)
}
// Java program for the above approach
import java.lang.Thread;
public class ThreadExample {
static boolean completed = false;
static int threadNumber = 1;
static void Thread1()
{
boolean doWhile = false;
while (!completed || !doWhile) {
doWhile = true;
while (threadNumber == 2) {
Thread.yield();
}
threadNumber = 2;
}
}
static void Thread2()
{
boolean doWhile = false;
while (!completed || !doWhile) {
doWhile = true;
while (threadNumber == 1) {
Thread.yield();
}
threadNumber = 1;
}
}
static void StartThreads()
{
Thread t1 = new Thread(ThreadExample::Thread1);
Thread t2 = new Thread(ThreadExample::Thread2);
t1.start();
t2.start();
}
// Driver Code
public static void main(String[] args)
{
threadNumber = 1;
StartThreads();
}
}
def Thread1():
doWhile=False
while not completed or not doWhile:
doWhile=True
# entry section
# wait until threadnumber is 1
while (threadnumber == 2):
pass
threadnumber = 2
# remainder section
def Thread2():
doWhile=False
while not completed or not doWhile:
doWhile=True
# entry section
# wait until threadnumber is 2
while (threadnumber == 1):
pass
threadnumber = 1
# remainder section
if __name__ == '__main__':
thread_number = 1
startThreads()
using System.Threading;
class ThreadExample {
static bool completed = false;
static int threadNumber = 1;
static void Thread1()
{
bool doWhile = false;
while (!completed || !doWhile) {
doWhile = true;
// entry section
// wait until threadNumber is 1
while (threadNumber == 2) {
Thread.Yield();
}
// critical section
// exit section
// give access to the other thread
threadNumber = 2;
// remainder section
}
}
static void Thread2()
{
bool doWhile = false;
while (!completed || !doWhile) {
doWhile = true;
// entry section
// wait until threadNumber is 2
while (threadNumber == 1) {
Thread.Yield();
}
// critical section
// exit section
// give access to the other thread
threadNumber = 1;
// remainder section
}
}
static void StartThreads()
{
Thread t1 = new Thread(Thread1);
Thread t2 = new Thread(Thread2);
t1.Start();
t2.Start();
}
static void Main(string[] args)
{
threadNumber = 1;
StartThreads();
}
}
// This code is contributed by Shivhack999
let thread_number = 1;
function Thread1() {
let doWhile = false;
while (!completed || !doWhile) {
doWhile = true;
// entry section
// wait until threadnumber is 1
while (thread_number === 2) {
// pass
}
// critical section
// exit section
// give access to the other thread
thread_number = 2;
// remainder section
}
}
function Thread2() {
let doWhile = false;
while (!completed || !doWhile) {
doWhile = true;
// entry section
// wait until threadnumber is 2
while (thread_number === 1) {
// pass
}
// critical section
// exit section
// give access to the other thread
thread_number = 1;
// remainder section
}
}
startThreads();
2. Second Version of Dekker's Solution
To remove lockstep synchronization, it uses two flags to indicate its current status and updates them accordingly at the entry and exit section.
- Idea: Each process uses a Boolean flag to show intent.
- Execution: A process enters and sets its flag; other process checks before entering.
- Problem: If preempted after setting flag, both may enter → Mutual exclusion violated.
Main()
{
boolean thread1 = false;
boolean thread2 = false;
startThreads();
}
Thread1()
{
do {
while (thread2 == true);
thread1 = true;
thread1 = false;
} while (completed == false)
}
Thread2()
{
do {
while (thread1 == true);
thread2 = true;
thread2 = false;
} while (completed == false)
}
public class MutualExclusion {
// flags to indicate if each thread is in
// its critical section or not
boolean thread1 = false;
boolean thread2 = false;
// method to start the threads
public void startThreads() {
new Thread(new Runnable() {
public void run() {
thread1();
}
}).start();
new Thread(new Runnable() {
public void run() {
thread2();
}
}).start();
}
public void thread1() {
do {
// entry section
// wait until thread2 is in its critical section
while (thread2 == true);
// indicate thread1 entering its critical section
thread1 = true;
// critical section
// exit section
// indicate thread1 exiting its critical section
thread1 = false;
// remainder section
} while (completed == false);
}
public void thread2() {
do {
// entry section
// wait until thread1 is in its critical section
while (thread1 == true);
// indicate thread2 entering its critical section
thread2 = true;
// critical section
// exit section
// indicate thread2 exiting its critical section
thread2 = false;
// remainder section
} while (completed == false);
}
public static void main(String[] args) {
MutualExclusion me = new MutualExclusion();
me.startThreads();
}
}
def Thread1():
doWhile=False
while not completed or not doWhile:
doWhile=True
# entry section
# wait until thread2 is in its critical section
while (thread2):
pass
# indicate thread1 entering its critical section
thread1 = True
# critical section
# exit section
# indicate thread1 exiting its critical section
thread1 = False
# remainder section
def Thread2():
doWhile=False
while not completed or not doWhile:
doWhile=True
# entry section
# wait until thread1 is in its critical section
while (thread1):
pass
# indicate thread1 entering its critical section
thread2 = True
# critical section
# exit section
# indicate thread2 exiting its critical section
thread2 = False
# remainder section
if __name__ == '__main__':
# flags to indicate if each thread is in
# its critical section or not.
thread1 = False
thread2 = False
startThreads()
using System;
using System.Threading;
class Program
{
static bool thread1 = false;
static bool thread2 = false;
static bool completed = false;
static void Main(string[] args)
{
// Start both threads
Thread threadOne = new Thread(new ThreadStart(Thread1));
Thread threadTwo = new Thread(new ThreadStart(Thread2));
threadOne.Start();
threadTwo.Start();
}
static void Thread1()
{
do
{
// entry section
// wait until thread2 is in its critical section
while (thread2)
{
// Spin-wait
}
// indicate thread1 entering its critical section
thread1 = true;
// critical section
// exit section
// indicate thread1 exiting its critical section
thread1 = false;
// remainder section
}
while (!completed);
}
static void Thread2()
{
do
{
// entry section
// wait until thread1 is in its critical section
while (thread1)
{
// Spin-wait
}
// indicate thread2 entering its critical section
thread2 = true;
// critical section
// exit section
// indicate thread2 exiting its critical section
thread2 = false;
// remainder section
}
while (!completed);
}
}
let thread1InCriticalSection = false;
let thread2InCriticalSection = false;
function thread1() {
// entry section
Promise.resolve().then(() => {
// wait until thread2 is in its critical section
while (thread2InCriticalSection) {}
// indicate thread1 entering its critical section
thread1InCriticalSection = true;
// critical section
// exit section
// indicate thread1 exiting its critical section
thread1InCriticalSection = false;
// remainder section
thread1();
});
}
function thread2() {
// entry section
Promise.resolve().then(() => {
// wait until thread1 is in its critical section
while (thread1InCriticalSection) {}
// indicate thread2 entering its critical section
thread2InCriticalSection = true;
// critical section
// exit section
// indicate thread2 exiting its critical section
thread2InCriticalSection = false;
// remainder section
thread2();
});
}
thread1(); // start thread1
thread2(); // start thread2
3. Third Version of Dekker's Solution
To re-ensure mutual exclusion, it sets the flags before the entry section itself.
- Idea: Process sets its flag before entering waiting loop.
- Execution: Both cannot enter simultaneously, ensuring mutual exclusion.
- Problem: If both set flags at the same time, both wait forever → Deadlock possible.
Main()
{
boolean thread1wantstoenter = false;
boolean thread2wantstoenter = false;
startThreads();
}
Thread1()
{
do{
thread1wantstoenter = true;
while (thread2wantstoenter == true);
thread1wantstoenter = false;
} while (completed == false)
}
Thread2()
{
do {
thread2wantstoenter = true;
while (thread1wantstoenter == true);
thread2wantstoenter = false;
} while (completed == false)
}
class SharedData {
static boolean completed = false;
}
class Thread1 extends Thread {
private static boolean thread1wantstoenter = false;
private static boolean thread2wantstoenter = false;
@Override
public void run() {
do {
thread1wantstoenter = true;
// Entry section
// Wait until Thread2 wants to enter its critical section
while (thread2wantstoenter)
;
// Critical section
System.out.println("Thread1 is in the critical section");
// Exit section
// Indicate Thread1 has completed its critical section
thread1wantstoenter = false;
// Remainder section
} while (!SharedData.completed);
}
}
class Thread2 extends Thread {
private static boolean thread1wantstoenter = false;
private static boolean thread2wantstoenter = false;
@Override
public void run() {
do {
thread2wantstoenter = true;
// Entry section
// Wait until Thread1 wants to enter its critical section
while (thread1wantstoenter)
;
// Critical section
System.out.println("Thread2 is in the critical section");
// Exit section
// Indicate Thread2 has completed its critical section
thread2wantstoenter = false;
// Remainder section
} while (!SharedData.completed);
}
}
public class Main {
public static void main(String[] args) {
SharedData.completed = false;
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
thread1.start();
thread2.start();
// Assuming some condition when threads should stop
// For demonstration purposes, let's say after a certain time
try {
Thread.sleep(5000); // Sleep for 5 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
SharedData.completed = true; // Stop the threads
}
}
if __name__=='__main__':
# flags to indicate if each thread is in
# queue to enter its critical section
thread1wantstoenter = False
thread2wantstoenter = False
startThreads()
def Thread1():
doWhile=False
while (completed == False or not doWhile):
doWhile=True
thread1wantstoenter = True
# entry section
# wait until thread2 wants to enter
# its critical section
while (thread2wantstoenter == True):
pass
# critical section
# exit section
# indicate thread1 has completed
# its critical section
thread1wantstoenter = False
# remainder section
def Thread2():
doWhile=False
while (completed == False or not doWhile) :
doWhile=True
thread2wantstoenter = True
# entry section
# wait until thread1 wants to enter
# its critical section
while (thread1wantstoenter == True):
pass
# critical section
# exit section
# indicate thread2 has completed
# its critical section
thread2wantstoenter = False
# remainder section
using System;
using System.Threading;
class Program
{
private static AutoResetEvent thread1Event = new AutoResetEvent(false);
private static AutoResetEvent thread2Event = new AutoResetEvent(false);
private static bool completed = false;
static void Main()
{
StartThreads();
}
static void StartThreads()
{
// Create threads for Thread1 and Thread2
Thread t1 = new Thread(Thread1);
Thread t2 = new Thread(Thread2);
// Start the threads
t1.Start();
t2.Start();
// Wait for both threads to complete or a timeout
t1.Join(5000); // Set a timeout (adjust as needed)
t2.Join(5000); // Set a timeout (adjust as needed)
// If threads do not complete within the timeout, consider alternative handling
if (t1.IsAlive || t2.IsAlive)
{
Console.WriteLine("Threads did not complete within the timeout.");
// Perform additional handling or force termination as needed
}
else
{
Console.WriteLine("Both threads completed.");
}
}
static void Thread1()
{
do
{
// Entry section
thread1Event.Set();
// Wait until Thread2 wants to enter its critical section or completion
if (!completed)
{
thread2Event.WaitOne();
}
// Critical section
// Exit section
// Indicate Thread1 has completed its critical section
thread1Event.Reset();
// Remainder section
} while (!completed);
}
static void Thread2()
{
do
{
// Entry section
thread2Event.Set();
// Wait until Thread1 wants to enter its critical section or completion
if (!completed)
{
thread1Event.WaitOne();
}
// Critical section
// Exit section
// Indicate Thread2 has completed its critical section
thread2Event.Reset();
// Remainder section
} while (!completed);
}
}
let thread1wantstoenter = false;
let thread2wantstoenter = false;
let completed = false; // Variable to indicate if both threads have completed
// Function to simulate thread execution
async function runThread(threadName, wantstoenter, otherThreadWantsToEnter) {
do {
wantstoenter = true;
while (otherThreadWantsToEnter) {
// Wait for a random amount of time
await wait(100); // Simulating random wait time
}
// Entry section
// Wait until the other thread wants to enter its critical section
// Critical section
console.log(`${threadName} is in the critical section`);
// Exit section
// Indicate the current thread has completed its critical section
wantstoenter = false;
// Remainder section
console.log(`${threadName} is executing the remainder section`);
} while (!completed);
}
// Function to simulate waiting
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Start both threads
async function startThreads() {
await Promise.all([
runThread('Thread1', thread1wantstoenter, thread2wantstoenter),
runThread('Thread2', thread2wantstoenter, thread1wantstoenter)
]);
}
// Start the threads
startThreads().then(() => {
console.log("Both threads have completed their execution");
});
4. Fourth Version of Dekker's Solution
Uses small time interval to recheck the condition, eliminates deadlock, and ensures mutual exclusion as well.
- Idea: If conflict, one process resets its flag and retries after delay.
- Execution: Avoids deadlock by letting one back off.
- Problem: One process may repeatedly lose → Starvation (indefinite postponement).
Main()
{
boolean thread1wantstoenter = false;
boolean thread2wantstoenter = false;
startThreads();
}
Thread1()
{
do {
thread1wantstoenter = true;
while (thread2wantstoenter == true) {
thread1wantstoenter = false;
thread1wantstoenter = true;
}
thread1wantstoenter = false;
} while (completed == false)
}
Thread2()
{
do {
thread2wantstoenter = true;
while (thread1wantstoenter == true) {
thread2wantstoenter = false;
thread2wantstoenter = true;
}
thread2wantstoenter = false;
} while (completed == false)
}
public class TwoThreadMutex {
// flags to indicate if each thread wants to
// enter its critical section
private static boolean thread1wantstoenter = false;
private static boolean thread2wantstoenter = false;
public static void main(String[] args) {
startThreads();
}
private static void startThreads() {
Thread t1 = new Thread(TwoThreadMutex::Thread1);
Thread t2 = new Thread(TwoThreadMutex::Thread2);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void Thread1() {
do {
thread1wantstoenter = true;
while (thread2wantstoenter == true) {
// gives access to other thread
// wait for random amount of time
thread1wantstoenter = false;
thread1wantstoenter = true;
}
// entry section
// wait until thread2 wants to enter
// its critical section
// critical section
// exit section
// indicate thread1 has completed
// its critical section
thread1wantstoenter = false;
// remainder section
} while (completed == false);
}
private static void Thread2() {
do {
thread2wantstoenter = true;
while (thread1wantstoenter == true) {
// gives access to other thread
// wait for random amount of time
thread2wantstoenter = false;
thread2wantstoenter = true;
}
// entry section
// wait until thread1 wants to enter
// its critical section
// critical section
// exit section
// indicate thread2 has completed
// its critical section
thread2wantstoenter = false;
// remainder section
} while (completed == false);
}
}
if __name__ == '__main__':
# flags to indicate if each thread is in
# queue to enter its critical section
thread1wantstoenter = False
thread2wantstoenter = False
startThreads()
def Thread1():
doWhile=False
while (completed == False or not doWhile):
doWhile=True
thread1wantstoenter = True
while (thread2wantstoenter == True) :
# gives access to other thread
# wait for random amount of time
thread1wantstoenter = False
thread1wantstoenter = True
# entry section
# wait until thread2 wants to enter
# its critical section
# critical section
# exit section
# indicate thread1 has completed
# its critical section
thread1wantstoenter = False
# remainder section
def Thread2():
doWhile=False
while (completed == False or not doWhile):
doWhile=True
thread2wantstoenter = True
while (thread1wantstoenter == True) :
# gives access to other thread
# wait for random amount of time
thread2wantstoenter = False
thread2wantstoenter = True
# entry section
# wait until thread1 wants to enter
# its critical section
# critical section
# exit section
# indicate thread2 has completed
# its critical section
thread2wantstoenter = False
# remainder section
using System;
using System.Threading;
class Program
{
static object lockObject = new object(); // Lock object for synchronization
static bool completed = false;
static void Main()
{
// Start both threads
Thread thread1 = new Thread(Thread1);
Thread thread2 = new Thread(Thread2);
thread1.Start();
thread2.Start();
// Wait for both threads to complete
thread1.Join();
thread2.Join();
}
static void Thread1()
{
bool doWhile = false;
while (!completed || !doWhile)
{
doWhile = true;
lock (lockObject)
{
// Entry section
Monitor.Wait(lockObject); // Wait until signaled by Thread2
// Critical section
Console.WriteLine("Thread1 is in critical section");
completed = true; // Indicate completion
// Exit section
Monitor.Pulse(lockObject); // Notify Thread2
}
// Remainder section
}
}
static void Thread2()
{
bool doWhile = false;
while (!completed || !doWhile)
{
doWhile = true;
lock (lockObject)
{
// Entry section
Monitor.Wait(lockObject); // Wait until signaled by Thread1
// Critical section
Console.WriteLine("Thread2 is in critical section");
completed = true; // Indicate completion
// Exit section
Monitor.Pulse(lockObject); // Notify Thread1
}
// Remainder section
}
}
}
let thread1wantstoenter = false;
let thread2wantstoenter = false;
let completed = false; // Variable to indicate if both threads have completed
function startThreads() {
// Start both threads
Thread1();
Thread2();
}
function Thread1() {
do {
thread1wantstoenter = true;
while (thread2wantstoenter) {
// Gives access to other thread
// Wait for a random amount of time
thread1wantstoenter = false;
thread1wantstoenter = true;
}
// Entry section
// Wait until Thread2 wants to enter its critical section
// Critical section
// Exit section
// Indicate Thread1 has completed its critical section
thread1wantstoenter = false;
// Remainder section
} while (!completed);
}
function Thread2() {
do {
thread2wantstoenter = true;
while (thread1wantstoenter) {
// Gives access to other thread
// Wait for a random amount of time
thread2wantstoenter = false;
thread2wantstoenter = true;
}
// Entry section
// Wait until Thread1 wants to enter its critical section
// Critical section
// Exit section
// Indicate Thread2 has completed its critical section
thread2wantstoenter = false;
// Remainder section
} while (!completed);
}
// Start the threads
startThreads();
5. Dekker's Algorithm: Final and completed Solution
Idea is to use favoured thread notion to determine entry to the critical section. Favoured thread alternates between the thread providing mutual exclusion and avoiding deadlock, indefinite postponement, or lockstep synchronization.
- Idea: Combine flags (intent) + turn (priority).
- Execution: If both want to enter, turn decides who goes; after exit, turn is passed.
- Solution: Ensures Mutual Exclusion, Progress, and Bounded Waiting.
Main()
{
int favouredthread = 1;
boolean thread1wantstoenter = false;
boolean thread2wantstoenter = false;
startThreads();
}
Thread1()
{
do {
thread1wantstoenter = true;
while (thread2wantstoenter == true) {
if (favaouredthread == 2) {
thread1wantstoenter = false;
while (favouredthread == 2);
thread1wantstoenter = true;
}
}
favouredthread = 2;
thread1wantstoenter = false;
} while (completed == false)
}
Thread2()
{
do {
thread2wantstoenter = true;
while (thread1wantstoenter == true) {
if (favaouredthread == 1) {
thread2wantstoenter = false;
while (favouredthread == 1);
thread2wantstoenter = true;
}
}
favouredthread = 1;
thread2wantstoenter = false;
} while (completed == false)
}
public class Main {
static int favouredThread = 1;
static boolean thread1WantsToEnter = false;
static boolean thread2WantsToEnter = false;
static boolean completed = false; // Declaration of the shared variable
public static void main(String[] args) {
startThreads();
}
static void startThreads() {
Thread thread1 = new Thread(() -> Thread1());
Thread thread2 = new Thread(() -> Thread2());
thread1.start();
thread2.start();
}
static void Thread1() {
do {
thread1WantsToEnter = true;
while (thread2WantsToEnter) {
if (favouredThread == 2) {
thread1WantsToEnter = false;
while (favouredThread == 2);
thread1WantsToEnter = true;
}
}
favouredThread = 2;
thread1WantsToEnter = false;
} while (!completed);
}
static void Thread2() {
do {
thread2WantsToEnter = true;
while (thread1WantsToEnter) {
if (favouredThread == 1) {
thread2WantsToEnter = false;
while (favouredThread == 1);
thread2WantsToEnter = true;
}
}
favouredThread = 1;
thread2WantsToEnter = false;
} while (!completed);
}
}
if __name__ == '__main__':
# to denote which thread will enter next
favouredthread = 1
# flags to indicate if each thread is in
# queue to enter its critical section
thread1wantstoenter = False
thread2wantstoenter = False
startThreads()
def Thread1():
doWhile=False
while (completed == False or not doWhile) :
doWhile=True
thread1wantstoenter = True
# entry section
# wait until thread2 wants to enter
# its critical section
while (thread2wantstoenter == True) :
# if 2nd thread is more favored
if (favaouredthread == 2) :
# gives access to other thread
thread1wantstoenter = False
# wait until this thread is favored
while (favouredthread == 2):
pass
thread1wantstoenter = True
# critical section
# favor the 2nd thread
favouredthread = 2
# exit section
# indicate thread1 has completed
# its critical section
thread1wantstoenter = False
# remainder section
def Thread2():
doWhile=False
while (completed == False or not doWhile) :
doWhile=True
thread2wantstoenter = True
# entry section
# wait until thread1 wants to enter
# its critical section
while (thread1wantstoenter == True) :
# if 1st thread is more favored
if (favaouredthread == 1) :
# gives access to other thread
thread2wantstoenter = False
# wait until this thread is favored
while (favouredthread == 1):
pass
thread2wantstoenter = True
# critical section
# favour the 1st thread
favouredthread = 1
# exit section
# indicate thread2 has completed
# its critical section
thread2wantstoenter = False
# remainder section
using System;
using System.Threading;
public class MainClass
{
// to denote which thread will enter next
private static volatile int favouredThread = 1;
// flags to indicate if each thread is in
// queue to enter its critical section
private static volatile bool thread1WantsToEnter = false;
private static volatile bool thread2WantsToEnter = false;
private static volatile bool completed = false; // Assume completed is a boolean variable
public static void Main(string[] args)
{
Thread t1 = new Thread(Thread1);
Thread t2 = new Thread(Thread2);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine("Both threads have completed.");
}
private static void Thread1()
{
bool doWhile = false;
while (!completed || !doWhile)
{
doWhile = true;
thread1WantsToEnter = true;
// entry section
// wait until thread2 wants to enter
// its critical section
while (thread2WantsToEnter)
{
// if 2nd thread is more favored
if (favouredThread == 2)
{
// gives access to other thread
thread1WantsToEnter = false;
// wait until this thread is favored
while (favouredThread == 2)
{
// Busy wait
}
thread1WantsToEnter = true;
}
}
// critical section
// favor the 2nd thread
favouredThread = 2;
// exit section
// indicate thread1 has completed
// its critical section
thread1WantsToEnter = false;
// remainder section
}
}
private static void Thread2()
{
bool doWhile = false;
while (!completed || !doWhile)
{
doWhile = true;
thread2WantsToEnter = true;
// entry section
// wait until thread1 wants to enter
// its critical section
while (thread1WantsToEnter)
{
// if 1st thread is more favored
if (favouredThread == 1)
{
// gives access to other thread
thread2WantsToEnter = false;
// wait until this thread is favored
while (favouredThread == 1)
{
// Busy wait
}
thread2WantsToEnter = true;
}
}
// critical section
// favour the 1st thread
favouredThread = 1;
// exit section
// indicate thread2 has completed
// its critical section
thread2WantsToEnter = false;
// remainder section
}
}
}
let favouredThread = 1;
let thread1WantsToEnter = false;
let thread2WantsToEnter = false;
let completed = false;
function startThreads() {
const thread1 = new Thread(Thread1);
const thread2 = new Thread(Thread2);
thread1.start();
thread2.start();
}
function Thread1() {
do {
thread1WantsToEnter = true;
while (thread2WantsToEnter) {
if (favouredThread === 2) {
thread1WantsToEnter = false;
while (favouredThread === 2);
thread1WantsToEnter = true;
}
}
favouredThread = 2;
thread1WantsToEnter = false;
} while (!completed);
}
function Thread2() {
do {
thread2WantsToEnter = true;
while (thread1WantsToEnter) {
if (favouredThread === 1) {
thread2WantsToEnter = false;
while (favouredThread === 1);
thread2WantsToEnter = true;
}
}
favouredThread = 1;
thread2WantsToEnter = false;
} while (!completed);
}
// Mock Thread class for demonstration
class Thread {
constructor(task) {
this.task = task;
}
start() {
// In a real environment, you would start the thread execution here.
// For simplicity, we just directly call the task function.
this.task();
}
}
// Main function
function main() {
startThreads();
}
// Entry point
main();
This version guarantees a complete solution to the critical solution problem.
Summary of Versions
| Version | Mechanism | Problem |
|---|---|---|
| 1. Turn variable only | Strict alternation | No progress if one process exits permanently |
| 2. Flags (after entry) | Mutual exclusion attempt | Both may enter → violation |
| 3. Flags (before entry) | Ensures mutual exclusion | Deadlock possible |
| 4. Flags + random backoff | Avoids deadlock | Starvation (indefinite postponement) |
| 5. Final Dekker’s Algorithm | Flags + turn variable | Correct solution (ensures all 3 requirements) |