線程執行代碼出現結果跟老師說的不一樣
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減去一張票后的值嗎
2016-07-20
我覺得老師那結果是多次執行篩選出的結果,值得一提的是確實有一定概率出現老師的執行結果
2015-12-20
你的理解大致上是對的,但不是剛好打印的時候被窗口2減去一張票,過程是這樣的:
當第一個線程獲得CPU的時間片后,它的代碼恰好執行到println那一行后,剛準備輸出(但還沒有獲得tickets的值),這時候該線程的時間片被剝奪,等待下一次再獲得時間片。等到別的線程執行完后,該線程再次獲得時間片,它去訪問tickets變量,應該tickets變量是被別的線程自減過得,所以獲得不是4,而是一個比4小的值。由于這種運算在現在的CPU上很快,就會出現前三個都是2的情況。如果你給println語句加上一個synchronized同步鎖,你的結果一會一直是43210.
2015-12-20
對,你的想法是對的。要想結果和你預想的一致,就得使用線程同步機制,給線程加鎖。