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

来源:互联网 发布:个人记账软件 pc 编辑:程序博客网 时间:2024/05/18 23:25
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++;}@Overridepublic void run() {// TODO Auto-generated method stubwhile(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同步操作同样的效果。

个人链接:
--------------------------------
JavaMail实现(JAVA <wbr><wbr><wbr>SWING)新浪微博:http://weibo.com/cwtree

       JavaMail实现(JAVA <wbr><wbr><wbr>SWING)人人首页:www.renren.com/treelovexiaobei

       JavaMail实现(JAVA <wbr><wbr><wbr>SWING)优酷空间: http://i.youku.com/cwtree

       JavaMail实现(JAVA <wbr><wbr><wbr>SWING)科大首页:http://home.ustc.edu.cn/~cwtree/
--------------------------------





原创粉丝点击