• i++的原子性问题


    一、什么是原子性

      简单的可以理解为:操作是不可再分割的,比如;

    int i=0;

    但是i++的操作是可以再分的,比如:

    i++ 
    //分解后
    i=i+i

    上面的代码在多线程环境下取值是有问题的,比如:

    package com.example.demo.juc;
    
    /**
     * @author DUCHONG
     * @since 2019-01-07 19:11
     **/
    public class AtomicTest {
    
        public static void main(String[] args) {
    
            AtomicThread atomicTest=new AtomicThread();
            for (int i=1;i<=20;i++){
    
                new Thread(atomicTest).start();
            }
        }
    }
    
    class AtomicThread implements Runnable {
    
        private  int num=1;
        @Override
        public void run() {
            try {
                Thread.sleep(300);
                System.out.println(getNum());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public int getNum(){
            return num++;
        }
    }

    结果:

    这种问题当然可以通过加synchronized 关键字来解决,那有没有另外一种方案呢,答案肯定是有的,且在jdk1.5的时候就有了,那就是Atomic包下的原子类

    优化后:

    package com.example.demo.juc;
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * @author DUCHONG
     * @since 2019-01-07 19:11
     **/
    public class AtomicTest {
    
        public static void main(String[] args) {
    
            AtomicThread atomicTest=new AtomicThread();
            for (int i=1;i<=20;i++){
    
                new Thread(atomicTest).start();
            }
        }
    }
    
    class AtomicThread implements Runnable {
    
        private AtomicInteger at=new AtomicInteger(1);
        @Override
        public void run() {
            try {
                Thread.sleep(300);
                System.out.println(getNum());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public int getNum(){
            return at.getAndIncrement();
        }
    }

    看源码:

    构造函数中的值,是volatile类型的

    自增或者自减时,使用了CAS算法,CAS算法有三个操作数:

    内存值:A

    预估值:B

    新值:V 

    当且仅当 A=B 是 A=V 

    否则不做任何操作。

  • 相关阅读:
    解析ASP.NET Mvc开发之删除修改数据
    JavaScript module pattern精髓
    Remote验证及其改进(附源码)
    图模型的精确推理
    C#在泛型类中,通过表达式树构造lambda表达式
    类管理指针成员
    朴素贝页斯分类法
    使用Repository模式构建数据库访问层
    利用MVC的过滤器实现url的参数加密和解密
    在多线程中使用静态方法是否有线程安全问题
  • 原文地址:https://www.cnblogs.com/geekdc/p/10235283.html
Copyright © 2020-2023  润新知