前一章講解了線程不一樣步帶來的問題,最後也給你們留下了一個思考,下面是對該問題的分析。bash
@Override
public void run(){
String windowName=Thread.currentThread().getName();
while(ticket.count>0){
synchronized (ticket) {
ticket.count--;
System.out.println(windowName + "賣出一張票 剩餘票數" + ticket.count);
}
}
}
}
複製代碼
如上所示,該代碼的邏輯是經過對票數的數量進行判斷是否結束當前線程。問題就出在循環判斷這裏。 A和B兩個線程同時到達while語句,會對ticket數量進行判斷。若是數量大於0,則進入循環對ticket變量進行操做。ide
當ticket值爲1,A和B兩個線程都運行到while語句,會發現條件知足,因而都進入了while循環體。到達synchronized語句,這時A和B兩個線程發生競爭關係,爭奪ticket對象鎖。假設A線程得到對象鎖,那麼B線程只能阻塞在synchronized(ticket)這裏。A線程繼續執行,對ticket進行減1操做,這時ticket值爲0。代碼執行完畢後,A線程釋放鎖,B取得ticket對象鎖,開始對ticket進行減1操做,但此時ticket值爲0,再繼續操做就變成了-1。因此要想獲得正確的結果,就得在對ticket進行操做前再判斷一次,修改後的代碼以下:spa
@Override
public void run(){
String windowName=Thread.currentThread().getName();
while(ticket.count>0){
synchronized (ticket) {
if(ticket.count>0) {
ticket.count--;
System.out.println(windowName + "賣出一張票 剩餘票數" + ticket.count);
}
}
}
}
}
複製代碼