并发原子类AtomicInteger详解

原子类是对volatlie的补充,利用cas原理达到操作不可分割保证原子性,在多线程下粒度细,效率高,可以把锁定位在变量的级别,但是在高度竞争下效率不如锁。AtomicInteger可以对一个int进行原子更新AtomicInteger不能用作Integer的替代品 。但是可以利用工具对数值在多线程下的原子操作

源码分析

重要属性

//原子类底层真正的值,volatile修饰能保证可见性和禁止指令重排序
   private volatile int value;

构造方法

//构造方法
    /**
     * 构造一个原子类默认就是value初始值也就是0
     */
    public AtomicInteger() {
    }

 /**
     * 创造一个原子类对象,值为传入的初始值initialValue
     *
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

方法分析
原子类提供了一些常用方法,其中也提供了普通的操作方法,这些方法不能保证线程安全,故不重要,违背了原子类设计的思想

 /**
     * 返回原子类的值,并没加额外的线程安全措施
     *
     */
    public final int get() {
        return value;
    }

    /**
     * 设置原子类的值,并没加额外的线程安全措施
     *
     * @param newValue the new value
     */
    public final void set(int newValue) {
        value = newValue;
    }

下面是原子类符合设计初衷的方法,能对数值进行原子操作,底层利用的是CAS算法实现的,保证线程安全

  /**
     * 用给定的值跟新旧的值,返回旧值
     *
     */
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }

 /**
     * 如果当前值为 ==为预期值,则将该值原子设置为给定的更新值。
     *在多线程下会发生自旋,并发度高的情况下反而影响效率消耗资源
     *true如果成功。 False return表示实际值不等于预期值。不跟新
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

  }

    /**
     * 原子上增加一个当前值。返回旧值
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }


 /**
     * 原子上减小一个当前值。返回旧值
     *
     */
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }


  /**
     * 原子上增加给定的值。返回旧值
     *
     */
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }


  /**
     * 原子上增加一个值。返回新值
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }
 /**
     * 原子上较少一个值。返回新值
     *
     * @return the updated value
     */
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }
   

原理分析
private static final Unsafe unsafe = Unsafe.getUnsafe();这个类对象调用方法能原子操作,利用的是CAS原理,底层我就不粘贴了,因为我发现这个类的源码我打不开,下面对CAS原理分析看代码

public class S {
	static int expectedValue;

	public static void main(String[] args) throws InterruptedException {
		compareAndSet(0, 1);
	}

	private static int compareAndSet(int a, int b) {
	//判断预期值
		if (expectedValue == a ) {
		//如果等于预期值就更新
			expectedValue = b;
		}else {
		//否则返回原来的值
			return expectedValue;
		}
		return expectedValue;
	}
}

以上就是模拟CAS原理,原子类在进行操作时,会拿着期望值和旧的值比较,如过相等就用新的值代替旧的值,如果不想等说明有人更改了,就自旋更新新的期望值,在去做重复比较,直到成功,这样就能保证原子性

案例

public class S {
//原子整形,利用CAS原理保证原子性
static AtomicInteger a=new AtomicInteger();

	public static void main(String[] args) throws InterruptedException {
		Thread thread = new Thread(new VoDemo());
		Thread thread1 = new Thread(new VoDemo());
		thread.start();
		thread1.start();
		thread.join();
		thread1.join();
		System.out.println(a);
	}

	static class VoDemo implements Runnable {

		@Override
		public void run() {
			for (int i = 0; i < 10000; i++) {
				a.incrementAndGet();
			}

		}

	}
}

发现两个线程同时执行共20000次结果为20000,如果改成普通int,在线程里面a++发现每次结果都是大概14000左右

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值