在操作i++的时候,使用同步方法和锁没有效果
public class aaa implements Runnable {
static int count = 0;
public static void main(String[] args) {
aaa aaa = new aaa();
aaa.create();
}
public void create() {
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 1000; i++) {
aaa thread = new aaa();
executor.execute(thread);
}
executor.shutdown();
while (true){
if(executor.isTerminated()){
System.out.println("a " + count);
break;
}
}
}
@Override
public void run() {
this.test();
}
public synchronized void test() {
count++;
System.out.println(count);
}
}
或者
public void test() {
Lock lock = new ReentrantLock(true);
try {
lock.lock();
count++;
System.out.println(count);
} finally {
lock.unlock();
}
}
都可能得到错误的结果:
908
907
906
905
904
895
894
890
889
888
887
886
a 998
而使用同步代码块却没有这样的问题:
public void test() {
synchronized (aaa.class){
count++;
System.out.println(count);
}
}
结果:
993
994
995
996
997
998
999
1000
a 1000
我认为以上三种方法应该得到同样的结果,就是最后输出1000,并且count的自增是有顺序的,但是只有最后一种给出了正确的结果。
请问各位哥这个代码问题在哪儿呢?
内存可见性你完全没有考虑到,需要加上volatile关键字,这里涉及到jvm执行线程底层原理。虽然你控制了线程,但是线程之间是不知道这个i有无被修改的,因此需要加上volatile底层会调用CPU指令通知线程i被改了,这样线程就会自旋执行。
总之在count前加上volatile就可以解决问题了,更多知识慢慢研究吧。