import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Sd implements Runnable {
private int a = 1;
public int getA() {
return a;
}
private synchronized void oddIncrement() {
a++;
a++;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
oddIncrement();
}
}
}
public class SychronizedDemo {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
Sd sd = new Sd();
es.execute(sd);
while(true) {
int b = sd.getA();
if(b%2==0) {
System.out.println(b);
System.exit(0);
}
}
}
}
程序中,我们可以看到,a的初始值是1,然后oddIncrement()操作是连续两次给a增值操作,那么一次调用就是+2,所以a无论经过多少次增值操作,它都是一个奇数,
那么我们在主函数中判断%2==0的这个操作,按道理说应该是不可能的,但是事实却是相反,仍然会有偶数的b值打印在控制台。
这就说明原子操作是需要同步控制的。那么上面的问题出在什么地方呢?
我认为是getA这个方法上,在getA和oddIncrement方法之间,绝对存在某些操作操作使得getA值和oddIncrement方法有了偏差。
虽然oddIncrement操作进行了同步,但是getA并没有进行同步。我们尝试对getA方法也进行同步
public synchronized int getA() {
return a;
}
当我们再次运行以上程序时,发现控制台久久没有输出了。
我想,这样应该就没有问题了。
所以说在JAVA程序中,看似简单的原子操作,增值,取值,貌似不会被别的程序所打断,但是事实却不是如此。
以上是通过synchronized这个关键字来同步原子操作的两个方法,那么有一种更简便的方法是,对所操作的属性用原子类来定义即可:
private AtomicInteger a = new AtomicInteger(1);
public int getA() {
return a.get();
}
private void oddIncrement() {
a.addAndGet(2);
}
可以达到与上述synchronized同步操作同样的效果。