关于100有没有可能不会打印出来的问题

来源:7-7 交替打印

Super丶Lee

2021-11-27

new Thread(new Runnable() {
	@Override
    public void run() {
	    while (count < 100) {
		    synchronized (lock) {
	            if ((count & 1) == 0) {
	                System.out.println(Thread.currentThread().getName() + ":" + count++);
                }
            }
        }
    }
}, "偶数");

这是视频里打印偶数的线程代码。

这里while的条件是count < 100,注意到结果中出现了偶数:100,也就是说在count == 99时,该线程已经进入了while代码块。
有没有一种可能,偶数线程自打印完98后,再也没有被CPU调度,直到奇数线程打印完99后(此时count已经是100)才再次获取CPU,从而无法打印出100

如果存在这种可能,那这段代码就是依赖于执行环境的。记得在哪里看过一句话好像是说,不应该对CPU的速度和数量做任何假设。

刚才跑了一个测试,发现确实有很小的概率出现打印不出来100的情况。

写回答

2回答

花草木香丶忆花间相见

2022-11-03

这是代码的问题,两个线程都可能满足 while(count < 100) ,然后其中 1 个被卡在 synchronized 里,if 判断是否奇偶数的时候,再次判断一遍 count 条件就行 ,不过我这里用的 <= 

附调整后的代码参考:

 public class ThreadPrintNumQuestionOne {

    public static int count = 0;

    public static Object lock = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            while (count <= 100) {
                synchronized (lock) {
                    if (count <= 100 && (count & 1) == 0) {
                        System.out.println(Thread.currentThread().getName() + " 偶数:" + count++);
                    }
                }
            }
        }).start();

        new Thread(() -> {
            while (count <= 100) {
                synchronized (lock) {
                    if (count <= 100 && (count & 1) == 1) {
                        System.out.println(Thread.currentThread().getName() + " 奇数:" + count++);
                    }
                }
            }
        }).start();
    }

}

那么这样方案的缺点也会更多,1:多次判断 count ,效率低,2:当前奇/偶线程不满足本身该处理的数据的时候,要一直重复进行锁竞争,抢到锁的线程也不一定是满足打印数字的线程,效率更是大大折扣。

0
1
悟空
恩,这种方案虽然有缺点,不过更准确。
2022-11-05
共1条回复

悟空

2021-11-27

谢谢小伙伴的提醒,我觉得你说得对,这里确实存在很小的概率是你说的情况。

0
0

线程八大核心+Java并发原理及企业级并发解决方案

完整的并发知识网络+丰富的工作内容分享+50余道并发高频面试题

2512 学习 · 939 问题

查看课程