这个程序是怎么回事?为什么递减的情况下,小数会跑到大数上面去?

这个程序是怎么回事?为什么递减的情况下,小数会跑到大数上面去?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class SellTicket extends Thread {
 
    // 定义100张票
    // private int tickets = 100;
    // 为了让多个线程对象共享这100张票,我们其实应该用静态修饰
    private static int tickets = 100;
 
    @Override
    public void run() {
        // 定义100张票
        // 每个线程进来都会走这里,这样的话,每个线程对象相当于买的是自己的那100张票,这不合理,所以应该定义到外面
        // int tickets = 100;
 
        // 是为了模拟一直有票
        while (true) {
            if (tickets > 0) {
                System.out.println(getName() + "正在出售第" + (tickets--) + "张票");
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * 某电影院目前正在上映贺岁大片(红高粱,少林寺传奇藏经阁),共有100张票,而它有3个售票窗口售票,请设计一个程序模拟该电影院售票。
 * 继承Thread类来实现。
 */
public class SellTicketDemo {
    public static void main(String[] args) {
        // 创建三个线程对象
        SellTicket st1 = new SellTicket();
        SellTicket st2 = new SellTicket();
        SellTicket st3 = new SellTicket();
 
        // 给线程对象起名字
        st1.setName("窗口1");
        st2.setName("窗口2");
        st3.setName("窗口3");
 
        // 启动线程
        st1.start();
        st2.start();
        st3.start();
    }
}

http://img1.sycdn.imooc.com//climg/5d01dc8a0001f5ee03070555.jpg

正在回答

登陆购买课程后可参与讨论,去登陆

4回答

       同学你好,这是计算机底层的执行原理。对虚拟机来说,多线程时,指令有时候会乱序执行。这是底层执行原理的问题,同学暂时记住即可。

       如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

吃吃吃鱼的猫 2019-06-13 19:20:01

同学你好,原因如下:

1
System.out.println(getName() + "正在出售第" + (tickets--) + "张票");

将以上命令分为三步:

1
2
3
tickets=tickets;
输出语句;
tickets=tickets-1

输出语句对于虚拟机来说是很多条指令,多线程时,指令乱序执行。

例如,tickets初始值为100。

        1、线程A在执行tickets=tickets;后,将tickets=100存入寄存器,不执行输出语句,继续向下执行tickets=tickets-1;,将tickets=99存入内存。

        2、这时,线程B获取执行权,从内存读取tickets=99,向下执行,输出语句“正在出售第99张票",执行tickets=tickets-1;,tickets=98。

        3、线程A重新获取执行权,从寄存器读取tickets=100,输出“正在出售第100张票”。

解决方法:

        将这段代码包在同步代码块里,即加锁执行,如下图所示:

http://img1.sycdn.imooc.com//climg/5d02314d0001a4bb08760317.jpg

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

  • 提问者 岩爵 #1
    对于线程A这个线程来说,三条语句:1.tickets=tickets; 2.输出语句; 3.tickets=tickets-1;这三条语句是按照一定的顺序摆放的,线程A怎么可以不执行输出语句,而是跳过去执行tickets=tickets-1呢?最多只是卡在那里不执行了,别的线程抢到了执行权,怎么能跳过顺序语句执行呢?
    2019-06-13 19:49:44
吃吃吃鱼的猫 2019-06-13 16:51:05

同学你好,先输出语句,然后再进行减1操作哦~

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快

  • 提问者 岩爵 #1
    如果是先输出再减一的话,那么第一个应该是输出: 窗口2正在出售第100张票啊 ,然后100减1等于99,这样才符合程序啊,为什么99和98反而跑到100上面去了?
    2019-06-13 16:57:56
吃吃吃鱼的猫 2019-06-13 16:00:24

同学你好

1、SellTicket实现Runnable接口

2、在循环中,需要为该对象加锁。

3、当票数<0时,退出循环,程序不再执行。

原因如下:

CPU可能随机的在多个处于就绪状态中的线程中进行切换,这时就可能出现线程的安全问题;

解决安全问题则需要同步锁的加入,执行synchronized部分代码的时候必须需要对象锁,

而一个对象只有一个锁,只有执行完synchronized里面的代码后释放锁,其他线程才可以获得锁。

那么就保证了同一时刻只有一个线程访问synchronized里面的代码。实现资源共享的关键是:只有一个实例,synchronized使用的是同一把锁,用实例的锁或者定义一个实例。

这就需要使用实现Runnable接口的方式,实现多线程,这样传入的是一个实例。

继承Thread的方式,传入的是多个实例,每个实例都有一个锁,那就无法实现控制。

修改代码如下图所示:

http://img1.sycdn.imooc.com//climg/5d02021b0001555309610647.jpg

4、创建一个SellTicket对象

5、创建三个线程,将SellTicket对象传入

修改代码如下图所示:

http://img1.sycdn.imooc.com//climg/5d0202600001114307950502.jpg

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

  • 提问者 岩爵 #1
    在我原来的那个代码块里,那条输出语句中的 tickets-- , tickets的值减一,是发生在输出语句之前还是输出语句之后?
    2019-06-13 16:28:29
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师
插入代码