線程執(zhí)行代碼出現(xiàn)結(jié)果跟老師說的不一樣
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()?+?"賣了一張票,票數(shù)剩余" +?tickets); } } }
執(zhí)行結(jié)果?
窗口1賣了一張票,票數(shù)剩余2
窗口2賣了一張票,票數(shù)剩余2
窗口3賣了一張票,票數(shù)剩余2
窗口2賣了一張票,票數(shù)剩余0
窗口1賣了一張票,票數(shù)剩余1
請問,并不是打印出來4,3,2,1,0或者是亂序的4,3,2,1,0。這是怎么回事?難道是窗口1減去一張票后,剛好打印的時候被窗口2減去一張票,然后窗口一重新獲得cpu,然后打印的時候打印出來的是窗口2減去一張票后的值嗎
2016-07-20
我覺得老師那結(jié)果是多次執(zhí)行篩選出的結(jié)果,值得一提的是確實有一定概率出現(xiàn)老師的執(zhí)行結(jié)果
2015-12-20
你的理解大致上是對的,但不是剛好打印的時候被窗口2減去一張票,過程是這樣的:
當(dāng)?shù)谝粋€線程獲得CPU的時間片后,它的代碼恰好執(zhí)行到println那一行后,剛準(zhǔn)備輸出(但還沒有獲得tickets的值),這時候該線程的時間片被剝奪,等待下一次再獲得時間片。等到別的線程執(zhí)行完后,該線程再次獲得時間片,它去訪問tickets變量,應(yīng)該tickets變量是被別的線程自減過得,所以獲得不是4,而是一個比4小的值。由于這種運(yùn)算在現(xiàn)在的CPU上很快,就會出現(xiàn)前三個都是2的情況。如果你給println語句加上一個synchronized同步鎖,你的結(jié)果一會一直是43210.
2015-12-20
對,你的想法是對的。要想結(jié)果和你預(yù)想的一致,就得使用線程同步機(jī)制,給線程加鎖。