多线程并发之Atomic,(i++问题解决)

一、线程,是如此的不安全

首先我们先做一个小实验,运行以下程序

private   static int   count=0;
    private final  static int   threadNum=100;
    private final  static int   times=1000000;
    private static void inc(){
        count++;
    }
    public static void main(String[] args) {
        List ts=new ArrayList();
        for (int i = 0; i < threadNum; i++) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    for (int j = 0; j < times; j++) {
                        ThreadTest.inc();
                    }
                }
            });
            ts.add(t);
        }
        long time=System.currentTimeMillis();
        for (Thread t:ts) {
            t.start();
        }
        while (true) {
            int num = 0;
            for (Thread t : ts) {
                if(t.isAlive()) num++;
            }
            if(num==0) break;
            System.out.println("live thread :" +num);
            sleep(1000);
        }
        System.out.println("costTime:"+(System.currentTimeMillis()-time));
        System.out.println("you want num is " +(times*threadNum));
        System.out.println("the real num is " +(count));
    }

    private static void sleep(long ms){
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

运行结果如下

Paste_Image.png
Paste_Image.png

可以发现,每次结果都不一样。根据经验,我们遇到了线程安全的问题,小小的i++都不安全,还让不让活了。。。

二、i++的深刻检讨

显而易见,我们只有一个count共享变量,那么不安全的原因便是i++是不是原子操作的问题了。
i++有以下步骤:

1、内存到寄存器
2、寄存器自增
3、写回内存

任何一部都可能中断分离开,所以不是原子操作,从而发生了线程安全问题

三、解决办法之synchronized

我想多数人碰到这个问题就会想到这个词synchronized,那我们就试用一下
代码:

private static synchronized void inc(){  
    count++;    
}

结果:

多线程并发之Atomic,(i++问题解决)_第1张图片
Paste_Image.png
多线程并发之Atomic,(i++问题解决)_第2张图片
Paste_Image.png

可以看出,确实解决了这个问题,但是也影响了程序的性能(可能因为我机器原因,单确实影响了性能,而且会随着锁内运行时间的增大或循环次数增加而递增)

四、解决办法之Volatile

用synchronized解决了这个问题,但是较大的降低了执行速度,那么我们能不能使用量级较轻的synchronized:Volatile呢?
锁的特征是互斥和可见,而Volatile满足了可见性

你可能感兴趣的:(多线程并发之Atomic,(i++问题解决))