求大佬解答一下关于两个线程交替打印奇偶数的问题

2020-07-23 14:04:09 +08:00
 bee7

就是下面的代码是交替打印 0 到 100 的奇偶数,我这里的循环条件是 count 小于 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();
    }
}
2301 次点击
所在节点    Java
9 条回复
popesaga
2020-07-23 14:11:20 +08:00
count++ 不是原子操作,再了解一下 volatile 和 AtomicInteger 。一个线程在做 count < 100 判断的时候读到了 99,然后才有另外一个线程的 count++ 引起的新值 100 更新的操作,再接着一个释放锁一个获得锁,100 就会被打印出来。
sonice
2020-07-23 14:12:23 +08:00
用 AtomicInteger
araraloren
2020-07-23 14:13:14 +08:00
count 是 99 的时候可能让两个线程同时通过 while 条件。。
bee7
2020-07-23 14:14:16 +08:00
@popesaga 感谢大佬,懂了!!
JasonLaw
2020-07-23 15:07:54 +08:00
@popesaga #1
@bee7 #4

count++本身不是原子操作,但是代码里已经使用了内置锁保证了 count++的原子性。根本问题不是 count++,而是没有用锁保护好 count 这个共享可变变量,也就是两个线程可以“同时”执行 count < 100 判断。如果当前 count 是 99,奇线程执行判断成功,获取锁,但是在更新 count 值之前,这个时候奇线程中止了,轮到偶线程执行,虽然判断成功,但是没办法获取锁,不过等到奇线程释放锁之后,偶线程就可以获取到锁了,最后偶线程会打印出 100 。
eve1yb0dy
2020-07-23 16:36:11 +08:00
我关注楼主名字...起的有意思
kkkkkrua
2020-07-23 16:38:07 +08:00
这写法不过关啊,看看 Reentrantlock
M1NGc
2020-07-24 15:45:05 +08:00
用同步队列
Octopvs
2020-07-29 16:23:34 +08:00
用双重检查锁就可以,sync 前判断一次<100,sync 后再判断一次就好了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/692500

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX