Reputation: 236
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.
Upvotes: 2
Views: 120
Reputation: 48404
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
startst2
spawns t1
t2
invokes increment
before t1
has a chance ton
is locked for the duration of t2
's increment
Thread
joins t2
before t1
has a chance to increment
Thread
prints n
before t1
has a chance to increment
Upvotes: 1
Reputation: 36304
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.
Upvotes: 3
Reputation: 41168
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.
Upvotes: 8