由于线程在执行的时候是异步的,当所有线程操作共享数据时,有可以能出现都已经进入判断的情况下,共享数据已被改变,但是其后线程不知道,当线程醒来的时候,直接开始运行,这样就会出现数据不全安的问题。 错误原因: 多条语句操作一个共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导到共享数据的错误。
测试类
代码语言:javascript复制DemoRunnable run = new DemoRunnable();
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
Thread t3 = new Thread(run);
Thread t4 = new Thread(run);
t1.start();
t2.start();
t3.start();
t4.start();
实现类
代码语言:javascript复制public class DemoRunnable implements Runnable {
private int ticket = 100;
@Override
public void run() {
boolean flag = true;
while (flag) {
if (ticket > 0) { //线程进入判断后睡10豪秒
try {
Thread.sleep(10); //让每一条进入的线程都sleep 10豪秒
ticket--; //ticket也可以放到sleep上面,结果也是错的。
System.out.println(ticket);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
flag = false;
}
}
}
}
结果: //每次结果都是不一样的!!!切记。 0 -1 -2 -3
分析:上面的例子中有4条线程,4条进程都是在 ticket>0 时进入。假设此时ticket为1,按1、2、3、4顺序执行的。 线程1先 sleep 10豪秒,然后 ticket–后此时为0。 线程2先sleep 10豪秒,然后 ticket–后此时为-1。 线程3先sleep 10豪秒,然后 ticket–后此时为-2。 线程4先sleep 10豪秒,然后 ticket–后此时为-3。 由于是异步的,所以每次的错误并不一定是相同的。 由于每次,线程都已进入了判断,而每次sleep异至线程在执行上,都走到了一起,然后配来后分别各自执行各自的代码,此时所有线程都已绕过了if的判断,所以出现了问题。一般CPU是交替执行线程的,但是每个线程被sleep后CPU就交换了执行权,当CPU再切换过来时,实际上次代码并没有执行完。