qiezijiajia

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

最近招聘经常会问到别人i++和++i的区别,于是这里来总结一下,当然除了那个大家都知道的先加后加的区别;

在性能上的区别

1.i++,会创建一个tmp值来保存i值,所有会额外带来开销,而++i不会。当然这个性能区别不会特别明显,基本上可以忽略。

 

原子性比较

1.i++和++i是否都具有原子性?

答案是否定的,均不具有原子性,我们可以通过多线程来试一下是否是线程安全就明白了。

public class TestForBlock {

    static volatile Integer k=0;

    public static void main(String[] args) throws InterruptedException {

        Thread[] ts  =   new  Thread[1000];
        for(int i=0;i<1000;i++){

            ts[i]=new Thread(){

                public void run(){

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ++k;  //也可替换成k++再试一下
                }
            };
        }
        for (Thread t:ts)  {
            t.start();
        }

        for (Thread t:ts)  {
            t.join();
        }

        System.out.println(k);
    }
}

输出结果期望应该是为1000,但是结果并不是1000,可能是小于1000的某个值。

这里的k变量使用了volatile定义,也就是说保证了内存可见性,但是volatile并不能保证原子性,如果i++或++i具有原子性,那么输出结果应该是1000才对。

 

那如果想让i++具有原子性怎么解决?

方法一、通过加上同步关键字synchronized

 

方法二、通过使用原子类AtomicInteger

比如讲k的定义换成这个final AtomicInteger k=new AtomicInteger(0); 就能保证起++的原子性;
这里讲下碰到的一个问题,当把k替换成原子类后,并且将下面代码去掉
for (Thread t:ts)  {
            t.join();
        }
最后的输出结果是什么样的? 会不会有影响?
运行后,发现输出结果是840多,并不是1000, 是什么问题? 难道原子类也不具有原子性?
如果对join比较明白的话就会明白是怎么回事了。因为有1000个线程执行,每个线程均有sleep(10),这样导致子线程还未执行完就到了主线程来执行了,所以输出结果就不是1000了。
加上join后,会等待所有线程执行完毕,再执行主线程。
join后面单独再拿一篇文章来说明吧

 

posted on 2017-09-07 10:15  qiezijiajia  阅读(275)  评论(0编辑  收藏  举报