问答详情
源自:2-3 应用Runnable模拟卖票

线程执行代码出现结果跟老师说的不一样

public class salesTicketRunnable {
	public static void main(String[] args) {
		TicketsRun tc = new TicketsRun();
		Thread a = new Thread(tc, "窗口1");
		Thread b = new Thread(tc, "窗口2");
		Thread c = new Thread(tc, "窗口3");
		a.start();
		b.start();
		c.start();
	}
}
class TicketsRun implements Runnable {
	private int tickets = 5;

	public void run() {
		while (tickets > 0) {
			tickets--;
			System.out.println(Thread.currentThread().getName() + "卖了一张票,票数剩余"
					+ tickets);
		}
	}
}

执行结果 

窗口1卖了一张票,票数剩余2

窗口2卖了一张票,票数剩余2

窗口3卖了一张票,票数剩余2

窗口2卖了一张票,票数剩余0

窗口1卖了一张票,票数剩余1

请问,并不是打印出来4,3,2,1,0或者是乱序的4,3,2,1,0。这是怎么回事?难道是窗口1减去一张票后,刚好打印的时候被窗口2减去一张票,然后窗口一重新获得cpu,然后打印的时候打印出来的是窗口2减去一张票后的值吗

提问者:朱西瓜 2015-12-19 11:48

个回答

  • 哀幻暝
    2016-07-20 21:33:45

    我觉得老师那结果是多次执行筛选出的结果,值得一提的是确实有一定概率出现老师的执行结果

  • sxian_wang
    2015-12-20 21:18:57

    你的理解大致上是对的,但不是刚好打印的时候被窗口2减去一张票,过程是这样的:

    当第一个线程获得CPU的时间片后,它的代码恰好执行到println那一行后,刚准备输出(但还没有获得tickets的值),这时候该线程的时间片被剥夺,等待下一次再获得时间片。等到别的线程执行完后,该线程再次获得时间片,它去访问tickets变量,应该tickets变量是被别的线程自减过得,所以获得不是4,而是一个比4小的值。由于这种运算在现在的CPU上很快,就会出现前三个都是2的情况。如果你给println语句加上一个synchronized同步锁,你的结果一会一直是43210.

  • GoJavaPython
    2015-12-20 21:18:56

    对,你的想法是对的。要想结果和你预想的一致,就得使用线程同步机制,给线程加锁。