javaalgorithmconcurrencylivelock

Dekker's Algorithm for 3 processes (Doesn't Work)


i'm trying to do a simple program with Dekker's Algorithm but with 3 processes. Here's my code:

class DekkerAlg {

static final int iter = 2000000;
static volatile int sharedResource = 0;
/* Thread P wants to enter in the CS */
static volatile boolean wantp = false;
/* Thread Q wants to enter in the CS */  
static volatile boolean wantq = false;
/* Thread R wants to enter in the CS */  
static volatile boolean wantr = false;
/* Who's next? */
static volatile int turn = 1;

    class P extends Thread {
        public void run() {
            for (int i=0; i<iter; ++i) {
                wantp = true;
                while (wantq || wantr) {
                    if (turn == 2 || turn == 3) {
                        wantp = false;
                        while (turn == 2 || turn == 3)
                            Thread.yield();
                        wantp = true;
                    }
                }

                ++sharedResource;

                turn = 2;
                wantp = false;
            }
        }
    }

    class Q extends Thread {
        public void run() {
            for (int i=0; i<iter; ++i) {
                wantq = true;
                while (wantp || wantr) {
                    if (turn == 1 || turn == 3) {
                        wantq = false;
                        while (turn == 1 || turn == 3)
                            Thread.yield();
                        wantq = true;
                    }
                }

                --sharedResource;

                turn = 3;
                wantq = false;
            }
        }
    }

    class R extends Thread {
        public void run() {
            for (int i=0; i<iter; ++i) {
                wantr = true;
                while (wantp || wantq) {
                    if (turn == 1 || turn == 2) {
                        wantr = false;
                        while (turn == 1 || turn == 2)
                            Thread.yield();
                        wantr = true;
                    }
                }

                ++sharedResource;

                turn = 1;
                wantr = false;
            }
        }
    }

    DekkerAlg() {
        Thread p = new P();
        Thread q = new Q();
        Thread r = new R();
        p.start();
        q.start();
        r.start();

        try {
            p.join();
            q.join();
            r.join();
            System.out.println("Shared Resource value: " + sharedResource);
            System.out.println("Should be 2000000.");
        }
        catch (InterruptedException e) {}
    }

    public static void main(String[] args) {
        new DekkerAlg();
    }
}

I don't know if my code is 100% correct. If P wants to enter in the CS, first, he has to check if Q or R wants to enter too, if it isn't his turn, he waits. Same procedure with Thread Q and R.

I guess Dekker's Algorithm doesn't work for 3 processes but i need to know if my code is correct and why my program fail.

Thanks.


Solution

  • When trying to get an idea if any given implementation of an algorithm works, reason about it ("proof" of correctness) or test it.
    With your implementation, have Q assign P's id to turn, and don't (instantiate, start, and) join R.
    When refactoring to use instances of just one runnable class: volatile type[] declares a volatile reference to an array of type - you need something else.

    With more than two processes, your extension will starve the process that, without being done, sets turn to the id of a process that will never set turn to any other value (is done or terminated), and any other processes neither done or terminated.


    The difficult part will be mutual exclusion for 3 processes […] without [changing Dekker's] entire algorithm - you may find yourself retracing the history of MutEx implementations.
    Early one were created with a model of memory much different from the JVM Memory Model.