前一章讲解了线程不同步带来的问题,最后也给大家留下了一个思考,下面是对该问题的分析。
@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变量进行操作。
当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进行操作前再判断一次,修改后的代码如下:
@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);
}
}
}
}
}