也就是说,下面的代码交替打印从0到100的奇数和偶数。我的循环条件是计数小于100。
为什么最终输出结果达到100?如果它不是100,那么在跳出循环之后就不能执行它。
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();
}
}
当变量count
的值为99
时发生这种情况。
考虑两个有趣的场景:
count
的值为99。
现在,两个线程都通过了第一个过滤器,即if(count < 100)
。
现在,两个线程都将竞相获取变量lock
上的锁。
设CCD_ 6和CCD_。
场景1:如果A战胜B:
则if条件if((count & 1) == 0)
将失败,因为count
是奇数。
线程A没有打印任何内容,A释放锁,B获取锁。
现在,B打印值99,并将count
的值递增到100。
预期场景1
但是,可能会出现第二种情况。
场景2:如果B战胜A,A必须等待B完成:
CCD_ 11的值为99。
现在,两个线程都通过了第一个过滤器,即if(count < 100)
。
在这种情况下,if条件if((count & 1) == 1)
被传递为count
是奇数。
B打印值99并将CCD_ 15的值增加到100。
现在,A中的if条件if((count & 1) == 0)
也将通过,因为count
的值是偶数,即100。
因此,线程A打印100。
那么现在,如何解决这个问题
答案:
只需在线程a的if条件中引入一个条件来检查CCD_ 18。
if((count & 1) == 0 && count<100)
。
看看以下实现:
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();
}
}
输出:
偶线程: 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:我还建议您查看和研究wait()
和notify()
方法,并编写一个逻辑上更健壮的代码。