今天在写博客的时候,想弄个例子说明一下非原子操作的线程安全问题,下面就是这个例子
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
// 开启1000条线程让counter的count++,理想结果应该是1000
for (int i = 0; i < 1000; i++) {
new Thread() {
public void run() {
counter.inc();
};
}.start();
}
System.out.println(counter.getCount());
}
}
class Counter {
private int count;
public void inc() {
count++;
}
public int getCount() {
return count;
}
}
然后执行的结果是“意料之中”的,因为count++并不是原子操作,会有线程安全问题,所以输出的结果是小于1000的,然后我说用synchronized关键字来解决这个问题,就是在Counter的inc()方法上加上这个关键字,然后一运行就傻眼了,怎么输出结果还是小于1000,运行了多次都是这样,几乎要接近崩溃
然后思考了许久,才想起来,这特么的启动的1000个线程可能还没结束主线程就执行输出代码了呀!!!对对对,就是这个问题,然后我让主线程睡眠1秒(权宜之计),然后就输出了我梦寐以求的1000
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
// 开启1000条线程让counter的count++,理想结果应该是1000
for (int i = 0; i < 1000; i++) {
new Thread() {
public void run() {
counter.inc();
};
}.start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter.getCount());
}
}
这个故事告诉我们,对待线程要小心翼翼,不然一不下心就踏进无穷无尽的套路中不可自拔,希望同学们不要犯我这个错误,很多时候错误就发生在不经意的小细节!