Reputation: 11
That is, the following code prints odd and even numbers from 0 to 100 alternately. My loop condition is that count is less than 100.
Why does the final output result reach 100? If it's not 100, it can’t be executed after jumping out of the loop.
public class WaitNotifyPrintOddEvenSyn {
private static int count;
private static final Object lock = new Object();
//新建 2 个线程,一个只处理偶数,一个只处理奇数
//并且用 synchronized 来通信
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while(count < 100){
synchronized (lock){
if((count & 1) == 0){
System.out.println(Thread.currentThread().getName() + ": " + count);
count++;
}
}
}
}
}, "偶线程").start();
new Thread(new Runnable() {
@Override
public void run() {
while(count < 100){
synchronized (lock){
if((count & 1) == 1){
System.out.println(Thread.currentThread().getName() + ": " + count);
count++;
}
}
}
}
}, "奇线程").start();
}
}
Upvotes: 1
Views: 83
Reputation: 5321
This occurred when the value of variable count
was 99
.
Consider the 2 interesting scenarios:
The value of count
is 99.
Now both threads passed the first filter, that is if(count < 100)
.
Now both threads will race to acquire lock on variable lock
.
Let first thread = A
and second thread = B
.
Scenario 1: If A wins over B:
Then the if condition if((count & 1) == 0)
will fail because, count
is odd.
Nothing gets printed from thread A and A releases the lock and B acquires the lock.
Now, B prints value 99 and increment the value of count
to 100.
Scenario 1 was expected!
But, there can be a scenario 2.
Scenario 2: If B wins over A and A has to wait for B to get completed:
The value of count
is 99.
Now both threads passed the first filter, that is if(count < 100)
.
In this case, the if condition, if((count & 1) == 1)
get passed as count
is odd.
B prints the value 99 and increment the value of count
to 100.
Now, the if condition in A, if((count & 1) == 0)
will also pass, as value of count
is even, that is, 100.
So, thread A prints 100.
So now, how to solve this problem?
Answer:
Simply by just introducing a single condition in if condition of thread A to check if count<100
.
if((count & 1) == 0 && count<100)
.
Have a look at the following implementation:
public class WaitNotifyPrintOddEvenSyn {
private static int count;
private static final Object lock = new Object();
//新建 2 个线程,一个只处理偶数,一个只处理奇数
//并且用 synchronized 来通信
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while(count < 100){
synchronized (lock){
if((count & 1) == 0 && count<100){
System.out.println(Thread.currentThread().getName() + ": " + count);
count++;
}
}
}
}
}, "偶线程").start();
new Thread(new Runnable() {
@Override
public void run() {
while(count < 100){
synchronized (lock){
if((count & 1) == 1){
System.out.println(Thread.currentThread().getName() + ": " + count);
count++;
}
}
}
}
}, "奇线程").start();
}
}
Output:
偶线程: 0
奇线程: 1
偶线程: 2
奇线程: 3
偶线程: 4
奇线程: 5
偶线程: 6
奇线程: 7
偶线程: 8
奇线程: 9
偶线程: 10
奇线程: 11
偶线程: 12
奇线程: 13
偶线程: 14
奇线程: 15
偶线程: 16
奇线程: 17
偶线程: 18
奇线程: 19
偶线程: 20
奇线程: 21
偶线程: 22
奇线程: 23
偶线程: 24
奇线程: 25
偶线程: 26
奇线程: 27
偶线程: 28
奇线程: 29
偶线程: 30
奇线程: 31
偶线程: 32
奇线程: 33
偶线程: 34
奇线程: 35
偶线程: 36
奇线程: 37
偶线程: 38
奇线程: 39
偶线程: 40
奇线程: 41
偶线程: 42
奇线程: 43
偶线程: 44
奇线程: 45
偶线程: 46
奇线程: 47
偶线程: 48
奇线程: 49
偶线程: 50
奇线程: 51
偶线程: 52
奇线程: 53
偶线程: 54
奇线程: 55
偶线程: 56
奇线程: 57
偶线程: 58
奇线程: 59
偶线程: 60
奇线程: 61
偶线程: 62
奇线程: 63
偶线程: 64
奇线程: 65
偶线程: 66
奇线程: 67
偶线程: 68
奇线程: 69
偶线程: 70
奇线程: 71
偶线程: 72
奇线程: 73
偶线程: 74
奇线程: 75
偶线程: 76
奇线程: 77
偶线程: 78
奇线程: 79
偶线程: 80
奇线程: 81
偶线程: 82
奇线程: 83
偶线程: 84
奇线程: 85
偶线程: 86
奇线程: 87
偶线程: 88
奇线程: 89
偶线程: 90
奇线程: 91
偶线程: 92
奇线程: 93
偶线程: 94
奇线程: 95
偶线程: 96
奇线程: 97
偶线程: 98
奇线程: 99
PS: I would also suggest you to have a look at and study the wait()
and notify()
methods and write a more logically robust code.
Upvotes: 2