JAVA高并发之原子并发包详解

1.并发包之原子类型

在多线程中保证数据的原子性,一般用法有synchronized,lock显示锁,atomic原子包,在执行多线 程程序中性能如何?JMH示例如下:

package com.mxli.concurrent.atomicdemo;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@OutputTimeUnit(TimeUnit.MICROSECONDS)
@BenchmarkMode({Mode.AverageTime,Mode.Throughput})
public class AtomicDemoJMH01 {
    @State(Scope.Group)
    public static class synDemo{
        private  int x;
        public void synTest(){
            synchronized (this){
                x++;
            }
        }
    }
    @State(Scope.Group)
    public static class LockDemo{
        private int x;
        private final Lock lock=new ReentrantLock();

        public void lockTest(){
            try {
               lock.lock();
               x++;
            }finally {
                lock.unlock();
            }
        }
    }
    @State(Scope.Group)
    public static class AtomicDemo{
        AtomicInteger c=new AtomicInteger();
        public void atomicTest(){
            c.incrementAndGet();
        }
    }

    @Benchmark
    @Group("sync")
    @GroupThreads(20)
    public void syncmonitor(synDemo synDemo){
        synDemo.synTest();
    }
    @Benchmark
    @Group("lock")
    @GroupThreads(20)
    public void lock(LockDemo LockDemo){
        LockDemo.lockTest();
    }

    @Benchmark
    @Group("atomic")
    @GroupThreads(20)
    public void atomicmonitor(AtomicDemo atomicDemo){
        atomicDemo.atomicTest();
    }

    public static void main(String[] args) throws RunnerException {
        final Options opts=new OptionsBuilder().include(AtomicDemoJMH01.class.getSimpleName())
                .forks(1)
                .warmupIterations(10)
                .measurementIterations(10)
                .build();
        new Runner(opts).run();
    }
}
执行结果如下:
Benchmark                Mode  Cnt   Score   Error   Units
AtomicDemoJMH01.atomic  thrpt   10  52.812 ± 1.595  ops/us
AtomicDemoJMH01.lock    thrpt   10  35.348 ± 1.458  ops/us
AtomicDemoJMH01.sync    thrpt   10  22.686 ± 0.473  ops/us
AtomicDemoJMH01.atomic   avgt   10   0.392 ± 0.019   us/op
AtomicDemoJMH01.lock     avgt   10   0.570 ± 0.040   us/op
AtomicDemoJMH01.sync     avgt   10   1.012 ± 0.031   us/op

      **可以看出执行效率atomic>lock>synchronized** 

2.原子并发包之atomicInteger使用详解

  1. AtomicInteger final AtomicInteger a=new AtomicInteger(); 初始化值默认为0;
  1. getAndIncrement() 获取当前value的值、然后进行自增。
  1. incrementAndGet()先进行自增,在获取value的值。
  1. getAndDecrement() 获取当前value的值、在进行自减。
  1. decrementAndGet() 先进行自减、在获取value的值。
  1. compareAndSet() compareAndSet(1,12),当前值比较,如果值相等则更新为第二个参数值,返回为true,否则返回false
  1. weakCompareAndSet()与compareAndSet()用法一样。
  1. getAndAdd(int delta) getAndAdd(2)==0 如果value为0,则更新值value+delta、否则为否,基于自旋+CAS算法
  1. addAndGet(int delta)立即返回value+delta的值。
  1. set() 为value设置一个值、生成内存屏障、立即被其他线程看到
  1. lazyset()就是在不需要让共享变量的修改立刻让其他线程可见的时候,以设置普通变量的方式来 修改共享状态,可以减少不必要的内存屏障,从而提高程序执行的效率.

3.原子并发包之atomicInteger如何保持多线程下数据原子性
在这里插入图片描述

  1. Unsafe几乎全部由C++实现、在AtomicInteger中有一个volatile修饰的int 类型的value值
  1. 在Unsafe中compareAndSwapint 方法,简称CAS算法,在CAS算法中,V是内存值,旧的预期值为A,新的预期值为B,如果旧的预期值与内存值相等的时候,则更新内存中的值为B,否则什么都不做,Lock free

4.原子并发包之atomicboolean与AtomicLong

  1. 初始化 AtomicBoolean b=new AtomicBoolean(); 初始值为false
  1. compareAndSet()
  1. weakcompareAndSet()
  1. set()
  1. lazyset()
  1. getandset()与atomicInterger用法一样
  1. atomicboolean 通常用于多个线程操控下,某个flag开关控制,能够保证其原子性

5.原子并发包之AtomicReference

  1. AtomicReference 是一个泛型类,提供有参和无参两种构造函数、当使用无参数的时候,需要调用set()方法为其初始化一个value值、
  2. compareAndSet( )
  3. getandset()
    在这里插入图片描述
    1: 并发包中都是利用volatile+CAS算法无锁的操作来保证共享数据在多线程保证原子性
    volatile保证各个线程对数据的可见性、
    2:原子类型用自旋+CAS算法来保证线程的安全性和原子性(自旋的意思是不引起调用者睡眠,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,“自旋”一词就是因此而得名、与之相对的是互斥锁、互斥锁会进入睡眠状态、)
    3:自旋的特点可以看出,会占用比较大量的资源、自旋锁比较适用于锁保持比较短的情况下使用。
    ABA问题导致的原因
    1:当前值为A,一个线程对当前value更新为B,
    2:另外一个线程在更新A,
    3:此时线程进行CAS的时候,CAS能够成功,因为值从初始值A变为B,又变为A,但是CAS并不清楚其中value发生了变化,这就是ABA的问题。

6.解决ABA问题之AtomicStampedReference

  1. AtomicStampedReference 其实是在AtomicReference加了一个时间戳的概念,或者称为加上一个版本号,
  2. AtomicStampedReference ar=new AtomicStampedReference(“hello”,1);初始化加一个版本号
  3. getReference()获取当前引用值
  4. getstamp()获取当前引用值的stamp值(版本号)
  5. get()获取当前引用值和版本号,可以用int数组实现
    在这里插入图片描述
  1. compareAndSet()
    在这里插入图片描述true
    false
  1. weakCompareAndSet() 用法与上边一样
  2. set()
    在这里插入图片描述hi----2
  1. AtomicLongArray、AtomicIntegerArray、AtomicReferenceArray 用法
    在这里插入图片描述不在一一叙述。
  1. AtomicIntegerFieldUpdater,AtomicBooleanFieldUpdater,AtomicReferenceFieldUpdater 原子性更新对象属性的类、
    在这里插入图片描述1

在使用 AtomicIntegerFieldUpdater,AtomicBooleanFieldUpdater,AtomicReferenceFieldUpdater作为更新对象的时候,需要注意,未被volatile 修饰的成员变量无法原子性更新、类变量无法原子性更新(static),无法直接访问的成员变量无法直接更新(private),final 修饰的无法更新、父类成员变量无法原子性更新

  1. 原子包底层依赖类sun.misc.Unsafe
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值