2

Why n sometimes equals 1 or 2

private static int n = 0;

private static Thread t1, t2;

private synchronized static void increment() {
    n++;
}

public static void main(String[] args) {
    t1 = new Thread(new Runnable() {
        public void run() {
            increment();
        }
    });

    t2 = new Thread(new Runnable() {
        public void run() {
            t1.start();
            increment();
        }
    });

    t2.start();

    try {
        t2.join();
    } catch(InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println(n);
}

Shouldn't the increment method only allow one thread to execute it at any given moment?

Maybe it is the debugger, it seems that when I run it normally I always get 2 but when i debug the code it some times return 1.

3
  • It looks like because you have static Thread instances, I suggest you stop making everything static. Also, don't call t1.start(); in the t2 run method. Commented Jul 8, 2014 at 12:55
  • @ElliottFrisch - What will be the impact of static thread instances?. even if the thread instances weren't static, he would still end up with the same unpredictable behaviour . right? Commented Jul 8, 2014 at 13:01
  • 1
    @TheLostMind It isn't just the static Thread instances, I was observing that everything is static. Also, why have them? That is why not declare them in the main method? Commented Jul 8, 2014 at 13:05

3 Answers 3

8

It does, however it could happen in either order. You only wait for t2 to finish but not for t1 to finish.

Wait for t1 as well.

Sign up to request clarification or add additional context in comments.

Comments

3
private static int n = 0; 

private static Thread t1, t2;

private synchronized static void increment() {  // Lock will be on the "class" Object
    n++;
}

public static void main(String[] args) {
    t1 = new Thread(new Runnable() {
        public void run() {
            increment();
        }
    });

    t2 = new Thread(new Runnable() {
        public void run() {
            t1.start();           
// t1 starts after t2. Now, t1's increment might also be called or t2's increment() might also be called. If t2 calls increment(), then the join() method below (you are joining the in the main thread) will be completed and "n" will be printed (if t1 is not getting appropriate time of execution..)
            increment();
        }
    });

    t2.start();           // t2 starts first

    try {
        t2.join();
    } catch(InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println(n); // increment() might not have been called by t1
}

There is no guarantee that one thread would execute before another (even with synchronized condition..). So, you can join on both t1 and t2 . This will ensure you will always get output as 2.

Comments

1

I guess if the increment invocation in the run method of t2 takes place before the increment method of t1 is invoked in t1's run method, then n is locked and by the time t2 ends, t1 might still be running, but you're printing out n incremented by t2 before t1's increment is over.

To clarify:

  • t2 starts
  • t2 spawns t1
  • t2 invokes increment before t1 has a chance to
  • n is locked for the duration of t2's increment
  • main Thread joins t2 before t1 has a chance to increment
  • main Thread prints n before t1 has a chance to increment

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.