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

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

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--) + "张票");
			}
		}
	}
}
/*
 * 某电影院目前正在上映贺岁大片(红高粱,少林寺传奇藏经阁),共有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

同学你好,原因如下:

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

将以上命令分为三步:

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

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

  • 提问者 天才少年25 #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操作哦~

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

  • 提问者 天才少年25 #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

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

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

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

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

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

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