JAVA多线程中,原子操作的概念——原子操作真的不需要进行同步控制吗?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://xxlcube.blog.csdn.net/article/details/8568902
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同步操作同样的效果。
 

 

展开阅读全文

没有更多推荐了,返回首页