当前位置: 移动技术网 > IT编程>开发语言>Java > 初识java atomic

初识java atomic

2018年08月19日  | 移动技术网IT编程  | 我要评论

2018-8-19

  昨天看到java.util.concurrent.atomic相关的文章,之前有过留意但并未去了解,正好有空学习一下。本人理解atomic包是concurrent子包,当是为并发所用,拿int类型来说,

int i=0; i++; i++并没有做同步写处理,当并发去写时,就可能出现一个线程所写的结果被另外线程所写的结果覆盖,造成最终结果不符合预期,但是如果用synchronized修饰方法,

就是同步方法,与并发处理相冲突,atomic中的类型则可解决此问题,并发时,可理解为各线程尝试修改,不符合预期结果则更新数据重新尝试修改,可避免结果被覆盖情况。

  即可理解为synchronized严格同步为悲观锁,atomic为乐观锁,atomic中的类适合并发编程

以代码来展示:

public class atomictest {

    
    public static int clienttotal=10000;
    public static int threadtotal=200;
    public static int count=0;
    public static atomicinteger atomiccount=new atomicinteger(0);
    
    public static void main(string[] args) {
        try {
            test();
        } catch (interruptedexception e) {
            e.printstacktrace();
        }
    }

    public static void test() throws interruptedexception {
        executorservice pool = executors.newcachedthreadpool();
        final semaphore semphore= new semaphore(threadtotal);
        final countdownlatch latch=new countdownlatch(clienttotal);
        for(int i=0;i<clienttotal;i++) {
            pool.execute(()->{
                try {
                    semphore.acquire();
                    add();
                    addatomic();
                    semphore.release();
                } catch (interruptedexception e) {
                    e.printstacktrace();
                }
                latch.countdown();
            });
        }
        latch.await();
        pool.shutdown();
        system.out.println("count--"+count);
        system.out.println("atomiccount--"+atomiccount);
    }
    public static void add() {
        count++;
    }
    public static void addatomic() {
        atomiccount.incrementandget();
    }
    
}
view code

结果:

count--9998
atomiccount--10000

结果中看出,count不符合预期,部分计算值被覆盖,比如执行一段时间后,当count=1300,线程thread5与线程thread6同时读到这个值,thread5运算写入count=1301,

thread6由于执行运算时count不是最新值,也随之写入count=1301,此时thread6把thread5结果覆盖了,本来两个线程执行完成预期是1302,真实完成后却是1301,

而atomiccount则符合预期。

查看atomicinteger源码:

private volatile int value;
public final int incrementandget() {
        return unsafe.getandaddint(this, valueoffset, 1) + 1;
    }
public final int getandaddint(object o, long offset, int delta) {
        int v;
        do {
            v = getintvolatile(o, offset);
        } while (!compareandswapint(o, offset, v, v + delta));
        return v;
    }  
view code

从代码中可看出实现原理,private volatile int value;用volatile修饰value,这样每次写读写都是用最新的值,以下代码

do { 

  v = getintvolatile(o, offset);

} while (!compareandswapint(o, offset, v, v + delta));

即先获得最新的value值,然后比较运算后是否符合预期,符合则写入,不符合则返回false,又重新尝试,compareandswap即熟知的cas,此为原子操作,

即用volatile修饰符来保证最新值,用compareandswap方法来保证原子性。

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网