英文:
About two threads alternately printing odd and even numbers
问题
以下是翻译好的代码部分:
这段代码的作用是交替打印从 0 到 100 的奇数和偶数。循环的条件是计数小于 100。
为什么最终的输出结果会达到 100 呢?如果不是 100,那么在跳出循环后就无法执行。
public class WaitNotifyPrintOddEvenSyn {
private static int count;
private static final Object lock = new Object();
//创建两个线程,一个处理偶数,一个处理奇数
//使用 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();
}
}
英文:
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();
}
}
答案1
得分: 2
这是要翻译的内容:
发生在变量 count
的值为 99
时。
考虑这两种有趣的情况:
count
的值为 99。
现在两个线程都通过了第一个过滤器,即 if(count < 100)
。
现在两个线程将竞争获取变量 lock
上的锁。
令 第一个线程 = A
和 第二个线程 = B
。
情况1: 如果 A 胜过 B:
那么条件 if((count & 1) == 0)
将会失败,因为 count
是奇数。
线程 A 不会打印任何内容,然后释放锁,线程 B 获得锁。
现在,B 打印值 99 并将 count
的值增加到 100。
情况1 是预期的!
但是,还有可能出现情况2。
情况2: 如果 B 胜过 A 并且 A 必须等待 B 完成:
count
的值为 99。
现在两个线程都通过了第一个过滤器,即 if(count < 100)
。
在这种情况下,条件 if((count & 1) == 1)
将会通过,因为 count
是奇数。
B 打印值 99 并将 count
的值增加到 100。
现在,线程 A 中的条件 if((count & 1) == 0)
也会通过,因为 count
的值是偶数,即 100。
所以,线程 A 打印出 100。
那么,如何解决这个问题呢?
答案:
只需在线程 A 的条件语句中引入一个条件来检查 count < 100
。
if((count & 1) == 0 && count < 100)
。
请看以下实现示例:
public class WaitNotifyPrintOddEvenSyn {
private static int count;
private static final Object lock = new Object();
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();
}
}
输出:
(输出示例略)
附注: 我还建议您查看并学习 wait()
和 notify()
方法,并编写更具逻辑鲁棒性的代码。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论