关于两个线程交替打印奇数和偶数的内容。

huangapple go评论79阅读模式
英文:

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 &lt; 100){
                    synchronized (lock){
                        if((count &amp; 1) == 0){
                            System.out.println(Thread.currentThread().getName() + &quot;: &quot; + count);
                            count++;
                        }
                    }
                }
            }
        }, &quot;偶线程&quot;).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(count &lt; 100){
                    synchronized (lock){
                        if((count &amp; 1) == 1){
                            System.out.println(Thread.currentThread().getName() + &quot;: &quot; + count);
                            count++;
                        }
                    }
                }
            }
        }, &quot;奇线程&quot;).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 &lt; 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 &amp; 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 &lt; 100).

In this case, the if condition, if((count &amp; 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 &amp; 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&lt;100.

if((count &amp; 1) == 0 &amp;&amp; count&lt;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 &lt; 100){
                    synchronized (lock){
                        if((count &amp; 1) == 0 &amp;&amp; count&lt;100){
                            System.out.println(Thread.currentThread().getName() + &quot;: &quot; + count);
                            count++;
                        }
                    }
                }
            }
        }, &quot;偶线程&quot;).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(count &lt; 100){
                    synchronized (lock){
                        if((count &amp; 1) == 1){
                            System.out.println(Thread.currentThread().getName() + &quot;: &quot; + count);
                            count++;
                        }
                    }
                }
            }
        }, &quot;奇线程&quot;).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.

huangapple
  • 本文由 发表于 2020年7月23日 14:12:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/63047966.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定