overexchange
overexchange

Reputation: 1

Why this program runs in infinite loop? Mutual exclusion

Below is the java program with which i started learning about mutual exclusion.

class MutexVar{
    public static int Turn = 1;
}

class CriticalSection{
    private static int modelNumber =0;
    public static void setModelNumber(int number){
        modelNumber = number;
    }

    public static int getModelNumber(){
        return modelNumber;
    }
}

public class MutualExclusion{
    public static void main(String[] args){
        Thread threadObjRef = new Thread(new Runnable(){
            public void run(){
                int autoVar = 1;
                int newModelNumber = -1;
                while(true){
                    /*                               Non - critical section - start   */
                    System.out.println("\n" + "In  run() thread");
                    /*                               Non - critical section - end     */
                    while(MutexVar.Turn == 2){
                        //System.out.println("loop-run"); //infinite loop problem is here
                    }
                    /*                               Critical Section -start          */
                    CriticalSection.setModelNumber(autoVar);
                    newModelNumber = CriticalSection.getModelNumber();
                    MutexVar.Turn = 2;
                    /*                               Critical Section -end            */

                    /*                               Non - critical section - start   */
                    System.out.println("run() thread: " + newModelNumber + "\n");
                    autoVar = autoVar + 2;
                    /*                               Non - critical section - end     */
                }
            }
        });
        threadObjRef.start();
        int autoVar = 0;
        int newModelNumber = -1;
        while(true){

            /*                                       Non - critical section - start    */
            System.out.println("\n" + "In  main thread");
            /*                                       Non - critical section - end      */
            while(MutexVar.Turn == 1){
                //System.out.println("loop-main"); //infinite loop problem is here
            }
            /*                                       Critical Section -start           */
            CriticalSection.setModelNumber(autoVar);
            newModelNumber = CriticalSection.getModelNumber();
            MutexVar.Turn = 1;
            /*                                       Critical Section -end             */

            /*                                       Non - critical section - start    */
            System.out.println("main- thread: " + newModelNumber + "\n");
            autoVar = autoVar + 2;
            /*                                       Non - critical section - end      */
        }
    }
}

My question:

1) Is there a data race between two threads to set MutexVar.Turn?

2) If no, then this program looks good to me, But my program loops infinitely with below output. why infinite loop loop-run or loop-main?

In  main thread

In  run() thread
run() thread: 1


In  run() thread

My observation:

This looks like a Thread scheduling issue. I learnt that java threads are visible to windows OS because they are created internally using CreateThread() api of kernel32.dll and scheduled by OS as 1-1 threading model in windows. java program runs using java jdk 1.6 on windows 7 multi core OS.

Upvotes: 2

Views: 399

Answers (2)

NESPowerGlove
NESPowerGlove

Reputation: 5496

Read your code wrong at first. Looks like you have a stale value.

MutexVar.Turns value is never flushed for other threads to see the latest change. If you changed Turn to be declared as volatile or synchronized on some common lock when you read and write to the common variable shared between threads then you'll probably find MutexVar.Turns value to change.

Upvotes: 4

John Vint
John Vint

Reputation: 40256

Always synchronize access to shared mutable data. It's not exactly obvious what the JIT/CPU is doing but you are almost certainly running into thread-caching issues by using a non-volatile Turn. Declare MutrexVar as

static class MutexVar {
    public static volatile int Turn = 1;
}

Volatile on a keyword says, Each thread that reads this value will have the most up-to-date value and prohibits compiler reorderings.


A bit more detail of compiler re-orderings. The JIT compiler is able to take your code and hoist the read of Turn. For example it can transform

while(MutexVar.Turn == 1){
    //System.out.println("loop-main"); //infinite loop problem is here
}

into

if(MutexVar.Turn == 1) {
    while(true) {
        //System.out.println("loop-main"); //infinite loop problem is here
    }
 }

This in no way violates Java's compiler contract and can improve performance dramatically. Declaring the field volatile prevents this type or re-ordering.

Upvotes: 3

Related Questions