javamultithreadingconcurrency

Java Thread join() with sleep interval causing problem


I was doing tutorial on concurrent programming and saw .join() method is used to make sure the thread will run until finish before continue the rest of code.

However, when i trying use 2 thread to increment and decrements a variable like 100 times (initiate value: 2000), the end result suppose to show 2000, but it show either more than 2000 or less than 2000. It only works fine and consistently show 2000 when i uncomment the Thread.sleep in main method

public class Main {
    public static void main(String[] args) {
        SharedObj sharedObj = new SharedObj();
        Thread thread1 = new Thread(new ThreadMinus(sharedObj));
        Thread thread2 = new Thread(new ThreadPlus(sharedObj));
        thread1.start();
//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("number is: " + sharedObj.num);
        System.out.println("increment count: " + sharedObj.countPos);
        System.out.println("decrement count: " + sharedObj.countNeg);

    }
}

class SharedObj {
    public int num;
    public int countPos = 0;
    public int countNeg = 0;

    public SharedObj() {
        num = 2000;
    }

    public void change(int x) {
        num += x;
        if (x < 0) {
            countNeg++;
        } else {
            countPos++;
        }
        System.out.println("number is: " + num + " with operation: " + x);
    }
}

class ThreadMinus implements Runnable {
    SharedObj sharedObj;

    public ThreadMinus(SharedObj sharedObj) {
        this.sharedObj = sharedObj;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            sharedObj.change(-1);
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class ThreadPlus implements Runnable {
    SharedObj sharedObj;

    public ThreadPlus(SharedObj sharedObj) {
        this.sharedObj = sharedObj;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            sharedObj.change(+1);
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Solution

  • It's not the sleep/join causing problems. It's the race condition that you're incrementing the same variable without securing it. Add synchronized to SharedObj#change and you should be fine:

    public synchronized void change(int x) { //...