陈福福 2018-11-08 09:34 采纳率: 0%
浏览 739
已采纳

多线程同步问题 限制循环条件为什么不起作用

题目:
某公司组织年会,会议入场时有两个入口,在入场时每位员工都能获取一张双色球彩票,假设公司有100个员工,利用多线程模拟年会入场过程,
并分别统计每个入口入场的人数,以及每个员工拿到的彩票的号码。线程运行后打印格式如下:
编号为: 2 的员工 从后门 入场! 拿到的双色球彩票号码是: [17, 24, 29, 30, 31, 32, 07]
编号为: 1 的员工 从后门 入场! 拿到的双色球彩票号码是: [06, 11, 14, 22, 29, 32, 15]
//.....
从后门入场的员工总共: 13 位员工
从前门入场的员工总共: 87 位员工

测试类:
public class Demo {
public static void main(String[] args) {

    People p = new People();

    Thread t1 = new Thread(p, "前门");
    Thread t2 = new Thread(p, "后门");

    t1.start();
    t2.start();
}

}

会场类:

public class People implements Runnable{

private int front = 0;
private int back = 0;
private int count = 100;

public List<Integer> cai() {
    List<Integer> list = new ArrayList<>();
    for (int i = 0; i < 6; i++) {
        list.add((int) (1+Math.random()*32));
    }
    list.add((int)(1+Math.random()*15));
    return list;
}


public void run() {
    while (count > 0) {
        synchronized (this) {
            if ("前门".equals(Thread.currentThread().getName())) {
                System.out.println("第"+(100-count+1)+"名员工,从"+Thread.currentThread().getName()+"进,取出的双色球的号码为:"+cai());
                front++;
                count--;
            }else if ("后门".equals(Thread.currentThread().getName())) {
                System.out.println("第"+(100-count+1)+"名员工,从"+Thread.currentThread().getName()+"进,取出的双色球的号码为:"+cai());
                back++;
                count--;
            }
            if (count==0) {
                System.out.println("前门人数:"+front+"\r\n"+"后门人数:"+back);
            }
        }
    }
}

}

求问:while的条件count>0,为什么在同步代码块内,会多输出count=0,第101号员工的情况,while不应该筛掉了吗?

图片说明

  • 写回答

2条回答 默认 最新

  • 玄尺 2018-11-08 11:33
    关注

    我们先捋一遍你的逻辑,你实际上是开了两个线程,每一个线程都会打印一个随机向量。这里面有一个问题:
    图片说明
    在synchronized (this)这一行上,两个线程在争抢people锁对象,但是只会有一个人能够拿到这把锁,假如t1拿到这把锁了,但是t2就会阻塞到这一行上。
    如果线程t1速度很快,在t2没起来之前就把这100个人消费掉了,然后t1正常退出。这时候t2线程从阻塞中唤醒,紧跟着打印了t2线程名从后门进入。这个问题是一个必定会出现的问题,所以总会在最后打印101.

    解决方法就很简单了,在while循环进入就判断count是否到0了。这个问题让我想到了单例模式中经典面试题:double check的必要性中里层的check目的是什么?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题