当前位置: 代码迷 >> J2SE >> java编程思想里一个关于同步和原子性的多线程有关问题
  详细解决方案

java编程思想里一个关于同步和原子性的多线程有关问题

热度:226   发布时间:2016-04-23 19:47:50.0
java编程思想里一个关于同步和原子性的多线程问题
import java.util.concurrent.*;

public class AtomicityTest implements Runnable {

private int i = 0;

public int getValue() {
return i;
}

private synchronized void evenIncrement() {
i++;
i++;
}

@Override
public void run() {
while (true)
evenIncrement();
}

public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest();
exec.execute(at);

while (true) {
int val = at.getValue();
if (val % 2 != 0) {
System.out.println(val);
System.exit(0);
}
}

}


AtomicityTest 的evenIncrement()产生偶数,主线程getValue()获取偶数
疑问:evenIncrement()这个方法已经同步了,也就是这个方法里的操作不会被其他线程打断,每次的计算结果都是偶数,i的值怎么会是基数呢?

把getValue()同步就解决问题了,但我不明白,getValue()只是一个只读操作,同步与否有影响吗?
把i的类型替换成原子性操作的atomicInteger也能解决问题,而且不用再evenIncrement()方法上同步了


我就有一点很迷惑,getValue()有基数说明在evenIncrement()方法里执行i++时被打断了,但是他明明是同步的呀?不懂
------解决思路----------------------
当一个有syncronize修饰的方法被调用的时候, 其他所有加了syncronize的方法必须等待其执行完, 才能执行.... 而没有加syncronize的方法是不受影响的.
所以当你的 evenIncrement() 在被调用期间, 调用getValue()  是一点冲突都没有的, 所以会出现基数的情况.
但是当你的getValue()方法加上了 syncronize, 那么就会受到影响, 一个类中, 同时只能有一个 syncronize方法被调用.... 而没加修饰的不在限制呢!


------解决思路----------------------
getValue可能会在两次i++的之间被调用。synchronized修饰的方法只是加了1个锁,对于相同锁的方法会互斥,但是不代表这个方法具有原子性。
  相关解决方案