为什么这个代码运行的结果有11这个结果啊,我用debug调试的时候到10就退出了
package org.java.demo;
public class Demo {
public static void main(String[] args) {
MyThread mt1 =new MyThread();
mt1.setName("窗口1:");
MyThread mt2 =new MyThread();
mt2.setName("窗口2:");
MyThread mt3 =new MyThread();
mt3.setName("窗口3:");
mt1.start();
mt2.start();
mt3.start();
}
}
package org.java.demo;
public class MyThread extends Thread {
private static int ticket;
private static Object obj = new Object();
public void run() {
while (ticket < 10) {
synchronized (obj) {
ticket++;
try {
sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":售出的票的编号为:" + ticket);
}
}
}
}
因为这个ticket是临界资源,存在并发冲突的概率,
2个线程同时运行时,两边代码的顺序你是无法控制的,
while(ticket < 10){
// 两线程同时执行到这里,并进入了while循环,进行了2次加1,当然出现了11
另外,你调试是按单线程执行的,会无意识的控制步骤,所以一般不会出错。
解决方法就是把 while也加入 sync 同步代码块
因为调试进入断点的时候其它线程也没有执行了,就很难在调试的状态复现出多线程问题, 可以if(ticket >= 10) {
} 在这个if里面打断点试试 其它断点全部去掉,进入断点的时候就是出并发问题的时候。我可以说下为什么会出现11
比如当前ticket = 9 ,
1. 三个线程都执行完while判断的时候, 去抢锁,
2. 那第一个线程抢到了, 9变成了10 ,
3.接着第二个线程抢到了,但是判断在之前已经判断好了,所以继续执行,10变成11
4. 第三个线程亦然
在判断<10的时候,不知道锁有没有释放,就像去车站买票,只知道这个地方有票买,不知道有没有卖完就去排队,到你买了却不知道还有没有票,但是你就是要强行买(ticket++),所以就。。。,这时应该再问下还有没有票(再次判断ticket<10)