V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
bee7
V2EX  ›  Java

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

  •  
  •   bee7 · Jul 23, 2020 · 3087 views
    This topic created in 2107 days ago, the information mentioned may be changed or developed.

    就是下面的代码是交替打印 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();
        }
    }
    
    9 replies    2020-07-29 16:23:34 +08:00
    popesaga
        1
    popesaga  
       Jul 23, 2020   ❤️ 2
    count++ 不是原子操作,再了解一下 volatile 和 AtomicInteger 。一个线程在做 count < 100 判断的时候读到了 99,然后才有另外一个线程的 count++ 引起的新值 100 更新的操作,再接着一个释放锁一个获得锁,100 就会被打印出来。
    sonice
        2
    sonice  
       Jul 23, 2020
    用 AtomicInteger
    araraloren
        3
    araraloren  
       Jul 23, 2020
    count 是 99 的时候可能让两个线程同时通过 while 条件。。
    bee7
        4
    bee7  
    OP
       Jul 23, 2020
    @popesaga 感谢大佬,懂了!!
    JasonLaw
        5
    JasonLaw  
       Jul 23, 2020   ❤️ 1
    @popesaga #1
    @bee7 #4

    count++本身不是原子操作,但是代码里已经使用了内置锁保证了 count++的原子性。根本问题不是 count++,而是没有用锁保护好 count 这个共享可变变量,也就是两个线程可以“同时”执行 count < 100 判断。如果当前 count 是 99,奇线程执行判断成功,获取锁,但是在更新 count 值之前,这个时候奇线程中止了,轮到偶线程执行,虽然判断成功,但是没办法获取锁,不过等到奇线程释放锁之后,偶线程就可以获取到锁了,最后偶线程会打印出 100 。
    eve1yb0dy
        6
    eve1yb0dy  
       Jul 23, 2020
    我关注楼主名字...起的有意思
    kkkkkrua
        7
    kkkkkrua  
       Jul 23, 2020
    这写法不过关啊,看看 Reentrantlock
    M1NGc
        8
    M1NGc  
       Jul 24, 2020
    用同步队列
    Octopvs
        9
    Octopvs  
       Jul 29, 2020
    用双重检查锁就可以,sync 前判断一次<100,sync 后再判断一次就好了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2517 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 43ms · UTC 15:37 · PVG 23:37 · LAX 08:37 · JFK 11:37
    ♥ Do have faith in what you're doing.