简体   繁体   中英

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.

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

MutexVar.Turn s 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.Turn s value to change.

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.

You should never run a hard loop in a thread; at best, it wastes system resources, and it may lock out other threads. Your while loops on MutexVar.Turn should contain the following:

try {
   Thread.sleep (10);
} catch (InterruptedException e) {}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM