Java中12个原子(Atomic)操作类实现原理分析

Java之美[从菜鸟到高手演练]之atomic包的原理及分析 Atomic包是java.util.concurrent下的另一个专门为线程安全设计的Java包,包含多个原子操作类。这个包里面提供了一组原子变量类。其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,这只是一种逻辑上的理解。实际上是借助硬件的相关指令来实现的,不会阻塞线程(或者说只是在硬件级别上阻塞了)。 阅读详情

前言

我们知道i++操作实际上是线程不安全的,因为一个i++操作分为了三步:

  • 1、获取的i的值
  • 2、执行i+1
  • 3、将i+1的结果赋值给i

而这三步不是一个原子操作,多线程环境下就会出现线程不安全性问题。

Java从JDK 1.5开始,在
java.util.concurrent.atomic包下提供了12个对应的原子类操作,让我们可以直接使用原子操作类来实现一个原子的i++操作。

Java中一共提供了12个原子类操作,可以分为四种类型,分别是:

  • 原子更新基本类型
  • 原子更新数组
  • 原子更新引用
  • 原子更新属性

下面就让我们一起来看看这四大类中的12个原子操作类:

原子更新基本类型

原子更新基本数据类型有以下三个:

  • AtomicInteger:原子更新整型。
  • AtomicBoolean:原子更新布尔类型。
  • AtomicLong:原子更新长整型。

AtomicInteger

常用方法如下:

  • int addAndGet(int delta):
    以原子方式将传入的数值与实例中的值(AtomicInteger里的 value)相加,并返回结果。
  • boolean compareAndSet(int expect,int update):
    如果输入的数值等于预期值,则以原子方式将该值设置为输入的值,成功返回true,替换失败则返回false
  • int getAndIncrement():
    以原子方式将当前值自增1,并返回自增前的值。
  • int getAndDecrement():
    以原子方式将当前值自减1,并返回自减前的值。
  • void lazySet(int newValue):
    最终会设置成 newValue,注意这个方法是一个lazy方法,也就是说设置之后,并不会马上去将值更新到主内存,那么其他线程在一小段时间内可能看不到设置的值。
  • int getAndSet(int newValue):
    以原子方式将值设置为newValue,并返回旧值。

代码示例

package com.zwx.concurrent.atomic;

import java.util.concurrent.atomic.AtomicInteger;

public class TestAtomicBasicData {
    public static void main(String[] args) throws InterruptedException {
        AtomicInteger atomicInteger = new AtomicInteger(8);
        System.out.println("初始化:" + atomicInteger);//8
        atomicInteger.compareAndSet(8,10);
        System.out.println("CAS后:" + atomicInteger);//10
        System.out.println(atomicInteger.getAndIncrement());//自增1,返回自增前的值10
        System.out.println("自增后:" + atomicInteger);//11
        System.out.println(atomicInteger.getAndDecrement());//11
        System.out.println("自减后:" + atomicInteger);//10
    }
}

AtomicBoolean

更新boolean值,常用方法如下:

  • boolean compareAndSet(boolean expect,boolean update):
    如果输入的数值等于预期值,则以原子方式将该值设置为输入的值,成功返回true,替换失败则返回false。注意这里面实际上会先将boolean值转换为int类型,0-否 1-是
  • void lazySet(boolan newValue):
    最终会设置成 newValue,注意这个方法是一个lazy方法,也就是说设置之后,并不会马上去将值更新到主内存,那么其他线程在一小段时间内可能看不到设置的值。
  • boolean getAndSet(boolean newValue):
    以原子方式将值设置为newValue,并返回旧值。

AtomicLong

这个和上面的AtomicInteger几乎是一样的,就不在举例了。
原子操作都是利用Unsafe类中的CAS操作实现的,但是Unsafe中只提供了三种类型的CAS操作:


所以上面的boolean类型是转换为整型来CAS的,其他数据类型也可以先进行数据转换之后再通过CAS实现原子操作。

原子更新数组

原子操作更新数组也提供了三种类型:

  • AtomicIntegerArray:原子更Integer类型数组里的元素。
  • AtomicLongArray:原子更新Long类型数组里的元素。
  • AtomicReferenceArray:原子更新引用类型数组里的元素。

AtomicIntegerArray

 int[] arr = new int[]{1,2,3};
 AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(arr);


可以看到初始化之后将数组复制了一份,所以不会如果把值改变了,不会影响原有数组的值。

boolean compareAndSet(int i, int expect, int update):可以看到这个方法对比基本类型多了一个i,也就是index下标,其他方法也是一样和基本类型数组相比,多了一个index参数。

代码示例

package com.zwx.concurrent.atomic;

import java.util.concurrent.atomic.AtomicIntegerArray;

public class TestAtomicArray {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3};
        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(arr);
        atomicIntegerArray.compareAndSet(1,2,8);
        System.out.println(arr[1]);//原数组的值没被改变,还是2
        System.out.println(atomicIntegerArray.get(1));//atomicIntegerArray值被改变成8
    }
}

AtomicLongArray

和基本类型AtomicLong相比,方法都一样,也是多了一个index数组下标参数。

AtomicReferenceArray

这个方法也是一样,唯一的区别是可以传入一个泛型,也就是说数据中的元素时自定义的对象,而不是引用对象。

代码示例:

package com.zwx.concurrent.atomic;

import com.alibaba.fastjson.JSONObject;
import java.util.concurrent.atomic.AtomicReferenceArray;

public class TestAtomicReferenceArray {
    public static void main(String[] args) {
        Man man = new Man(18,"张三");
        Man[] arr = new Man[]{man};
        AtomicReferenceArray<Man> atomicReferenceArray = new AtomicReferenceArray<>(arr);
        System.out.println("CAS前:" + JSONObject.toJSONString(atomicReferenceArray.get(0)));//{"age":18,"name":"张三"}

        Man updateMan = new Man(28,"李四");
        atomicReferenceArray.compareAndSet(0,man,updateMan);
        System.out.println("CAS前:" + JSONObject.toJSONString(atomicReferenceArray.get(0)));//{"age":28,"name":"李四"}
    }
}

class Man{
    protected volatile Integer age;
    private String name;

    public Man(Integer age, String name) {
        this.age = age;
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

原子更新引用类型

原子更新基本类型时每次只能更新一个变量,如果我们需要原子更新多个变量,怎么做呢?这时候我们可以把多个变量和合成一个,那么就需要使用这个原子更新引用类型提供的类来更新了。

原子更新引用类型也提供了3个类:

  • AtomicReference:原子更新引用类型。
  • AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子更新一个布尔类 型的标记位和引用类型。
  • AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于原子的更新数据和数据的版本号,可以解决使用CAS进行原子更新时可能出现的ABA问题。

AtomicReference

需要先构造一个引用对象然后调用AtomicReference中的相关原子方法,我们先来看一段代码示例:

代码示例

package com.zwx.concurrent.atomic;

import com.alibaba.fastjson.JSONObject;
import java.util.concurrent.atomic.AtomicReference;

public class TestAtomicReference {
    public static void main(String[] args) {
        User oldUser = new User(18,"张三");
        AtomicReference<User> atomicReference = new AtomicReference<>(oldUser);
        System.out.println("CAS前:" + JSONObject.toJSONString(atomicReference.get()));//{"age":18,"name":"张三"}

        User upateUser = new User(28,"李四");
        boolean result =atomicReference.compareAndSet(oldUser,upateUser);
        System.out.println("CAS结果为:" + result);//true
        System.out.println("CAS后:" + JSONObject.toJSONString(atomicReference.get()));//{"age":28,"name":"李四"}
    }
}

class User{
    volatile Integer age;
    private String name;

    public User(Integer age, String name) {
        this.age = age;
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

这里的原理也是一样,通过Uasafe的CAS操作Object对象实现原子操作:

AtomicMarkableReference

这个和上面AtomicReference基本一致,唯一的区别是多了一个mark标记,boolean类型。

示例

package com.zwx.concurrent.atomic;

import com.alibaba.fastjson.JSONObject;
import java.util.concurrent.atomic.AtomicMarkableReference;

public class TestAtomicReferenceMark {
    public static void main(String[] args) {
        Person person = new Person(18,"张三");
        AtomicMarkableReference atomicMarkableReference = new AtomicMarkableReference(person,false);
        System.out.println("是否被标记过:" + atomicMarkableReference.isMarked());

        System.out.println("CAS前:" + JSONObject.toJSONString(atomicMarkableReference.getReference()));//{"age":18,"name":"张三"}

        Person updatePerson = new Person(28,"李四");
        /**
         * arg1:表示预期的引用对象
         * arg2:表示即将更新的引用对象
         * arg3:表示预期的标记
         * arg4:表示更新的标记
         * 需要参数1和参数3都是预期值才会CAS成功
         */
        atomicMarkableReference.compareAndSet(person,updatePerson,false,true);
        System.out.println("CAS后:" + JSONObject.toJSONString(atomicMarkableReference.getReference()));//{"age":28,"name":"李四"}
    }
}

class Person{
    private Integer age;
    private String name;

    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

AtomicMarkableReference原理分析


初始化对象的时候需要初始化一个引用对象和一个初始mark,而这两个属性又是通过其静态内部类Pair来管理的:

AtomicStampedReference

这个和AtomicMarkableReference几乎一模一样,唯一的区别就是AtomicMarkableReference中的标记只有true和false,而AtomicStampedReference中的标记是一个int类型,可以视作版本号,可以解决CAS的ABA问题。

原子更新属性

  • AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
  • AtomicLongFieldUpdater:原子更新长整型字段的更新器。
  • AtomicReferenceFieldUpdater:原子更新引用类型里的任意指定字段。

AtomicIntegerFieldUpdater

这个是用来更新引用对象中的int类型的属性,利用反射修改属性。有以下几点需要注意:

  • 引用类型中的属性必须是int,不能是包装类Integer
  • 引用类型中的属性必须被volatile修饰
  • 引用类型中的属性不能被private修饰

代码示例

package com.zwx.concurrent.atomic;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

public class TestAtomicReferenceField {
    public static void main(String[] args) {
        //AtomicIntegerFieldUpdater
        Women women = new Women(18,"张三");
        //arg1:引用的对象类型 arg2:要修改的对象中的属性名
        AtomicIntegerFieldUpdater atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Women.class,"age");
        atomicIntegerFieldUpdater.compareAndSet(women,18,28);
        System.out.println("CAS后的值:" + women.getAge());//28
    }
}

class Women{
    volatile int age;
    private String name;

    public Women(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

newUpdater方法:



AtomicIntegerFieldUpdaterImpl中初始化中就是利用反射获取属性修改属性,并进行了一些验证:

AtomicLongFieldUpdater

这个和上面AtomicLongFieldUpdater基本一样,用来更新long类型的属性,同样有以下几点需要注意:

  • 引用类型中的属性必须是long,不能是包装类Long
  • 引用类型中的属性必须被volatile修饰
  • 引用类型中的属性不能被private修饰

AtomicReferenceFieldUpdater

上面两个都是只能更新指定数据类型,而这个可以更新任意指定类型的属性。也有以下几个注意点:

  • 引用类型中的属性不能是原始数据类型,必须用对应包装类(这点和上面的两种相反)
  • 引用类型中的属性必须被volatile修饰
  • 引用类型中的属性不能被private修饰

示例

package com.zwx.concurrent.atomic;

import com.alibaba.fastjson.JSONObject;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

public class TestAtomicReferenceField {
    public static void main(String[] args) {
        /**
         * arg1:传入引用对象类型
         * arg2:传入引用对象的属性类型
         * arg3:传入要修改的属性名
         */
        AtomicReferenceFieldUpdater atomicReferenceFieldUpdater1 = AtomicReferenceFieldUpdater.newUpdater(Women.class,Integer.class,"age");
        AtomicReferenceFieldUpdater atomicReferenceFieldUpdater2 = AtomicReferenceFieldUpdater.newUpdater(Women.class,String.class,"name");

        Women women = new Women(18,"张三");
        atomicReferenceFieldUpdater1.compareAndSet(women,18,28);
        atomicReferenceFieldUpdater2.compareAndSet(women,"张三","李四");
        System.out.println(JSONObject.toJSONString(women));//{"age":28,"name":"李四"}
    }
}

class Women{
    volatile Integer age;
    volatile String name;

    public Women(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

CAS操作ABA问题

前面在讲述AQS同步队列的文章里提到了ABA问题可以通过引入一个版本号来和实际值拼在一起来避免ABA问题,那么实际上我们同样可以利用AtomicMarkableReference和AtomicStampedReference来实现,不过如果用AtomicMarkableReference只有true和false两种标记,而对于AtomicStampedReference就更自由,实际可以根据业务需求进行选择。

总结

本文介绍了Java中提供的12种原子操作类,原理均是通过Unsafe类中的CAS方法实现的,一般的CAS方法有可能会出现ABA问题,所以有一种带标记,一种带版本号的原子操作可以用于避免ABA问题的产生。

java线程-AtomicInteger原子类实现原理 上面的代码并非线程安全的,问题主要出现在count变量的不可见性和count+=1并非原子性操作,之前的解决方式都是使用Synchronized或者java sdk加锁的方式来保证原子性,使用volatile来保证可见性。在java线程-Lock详解&AQS原理详解一文中,发现大量使用了自旋+CAS操作,来保证线程安全性,这是一种无锁的操作,性能会比加锁的方式高很多。 阅读详情

相关推荐

详解Java中的原子操作

大家好,我是小黑,面试中一个经常被提起的话题就是“原子操作”。那么,到底什么是原子操作呢?在编程里,当咱们谈论“原子操作”时,其实是指那些在执行过程中不会被线程调度机制打断的操作。这种操作要么完全执行,要么完全不执行,没有中间状态。这就像是化学里的原子,不可分割,要么存在,要么不存在。举个简单的例子,想象一下,小黑在网上银行转账给朋友。这个操作要么完整完成——钱从小黑的账户转到朋友账户,要么根本就不发生——钱还在小黑的账户里。

BASK2311的博客 1196

java中atomic的原理

原子性能够解决竞态条件问题,确保对共享数据的操作是原子的,即要么所有线程都看到操作前的值,要么所有线程都看到操作后的值,不存在中间状态。在多线程环境下,原子性确保对共享变量的操作是不可分割的,不会被其他线程的操作干扰。类提供了一种实现原子操作的机制,确保在多线程环境下对共享变量的操作是原子的,即不会被其他线程中断。类中,本地方法被用来直接操作底层的硬件或操作系统提供的原子操作指令,从而保证操作的原子性。关键字保证了对变量的读取和写入是原子的,即一个线程的写入操作对其他线程立即可见。

cpy1356140308的博客 1085

「死磕Java并发编程」说说Java Atomic 原子类的实现原理

<!-- TOC --> - [线程安全真的是线程的安全吗?](#线程安全真的是线程的安全吗) - [什么是 Atomic?](#什么是-atomic) - [实现一个计数器](#实现一个计数器) - [AtomicInteger 源码分析](#atomicinteger-源码分析) - [AtomicLong 和 LongAdder 谁更牛?](#atomiclong-和-longadder-谁更牛) - [总结](#总结) <!-- /TOC --> ..

华科硕士,大厂打工中。编程问题咨询,请私我 1万+

Java原子性操作之——Atomic包的原理分析

Atomic:    Atomic包是java.util.concurrent下的另一个专门为线程安全设计的java的包,包含多个原子性操作的类。基本特性就是在多线程情况下,当多个线程想要同时操作这些类的某些实例方法时,具有排他性,也就是当某个线程在执行某个方法时,不会被其他线程打断,其他线程会在外部等待,一直等到该方法执行完毕,才由JVM从等待队列中选择另一个线程进入,这只是一种逻辑上的理解。实...

java_ying的博客 5359

Java开发者必看:Apache PDFBox实现PDF数字签名完整指南(附源码)

本文为Java开发者提供了使用Apache PDFBox实现PDF数字签名的完整指南。详细介绍了从环境配置、核心原理到完整代码实现的全过程,涵盖证书管理、签名位置计算、性能优化及实际应用案例,并附有可直接复用的源码,帮助开发者高效集成PDF数字签名功能。

o1p2q3r的博客 340

旧版Linux安装新NVIDIA显卡“No devices were found”排查实战

在Linux系统里安装NVIDIA闭源驱动,本质是加载内核模块并让它在PCIe总线上匹配设备ID。当遇到“No devices were found”这类提示,很多人误以为显卡损坏,其实问题常出在驱动层与硬件间的兼容链路。新架构显卡(如RTX 5090)对内核版本、BAR窗口、nouveau冲突等都有更高要求,而老发行版(如麒麟V10)的内核相对保守,nvidia-smi自然无法识别设备。本文从基础概念出发,讲解如何用lspci、lsmod、dmesg定位问题层级,系统梳理禁用nouveau、升级内核与工具

weixin_42638178的博客 301

c++ 原子操作 赋值_Java中12个原子(Atomic)操作类实现原理分析

前言我们知道i++操作实际上是线程不安全的,因为一个i++操作分为了三步:1、获取的i的值2、执行i+13、将i+1的结果赋值给i而这三步不是一个原子操作,多线程环境下就会出现线程不安全性问题。Java从JDK 1.5开始,在java.util.concurrent.atomic包下提供了12个对应的原子类操作,让我们可以直接使用原子操作类来实现一个原子的i++操作。Java中一共提供了12个原子...

weixin_39616379的博客 514

YOLOv5改进——添加SimAM注意力机制

这样可以使注意力机制看到整个backbone部分的特征图,将具有全局视野,类似于一个小的transformer结构。注意:很多改进教程都是将代码直接复制到common.py文件,如果改进机制多了容易造成混乱。在models文件夹下新建modules文件夹,在modules文件夹下新建一个py文件。这里为simam.py。在models文件夹下,复制yolov5s.yaml文件,粘贴并重命名为yolov5s-simam.yaml。运行yolo.py,出现刚刚加入的SimAM注意力机制,说明加入成功。

2302_80099075的博客 1654

【并发编程系列11】Java中12个原子(Atomic)操作类实现原理分析

Java中的12个原子操作类前言原子更新基本类型AtomicInteger代码示例AtomicBooleanAtomicLong原子更新数组AtomicIntegerArray代码示例AtomicLongArrayAtomicReferenceArray代码示例:原子更新引用类型AtomicReference代码示例AtomicMarkableReference示例AtomicMarkableReference原理分析AtomicStampedReference原子更新属性AtomicIntegerFiel

zwx900102的博客 1337

CST实战:变容二极管电容曲线提取全流程(附S参数设置技巧)

本文详细介绍了在CST Studio Suite中提取变容二极管电容-电压(C-V)曲线的完整实战流程。重点解析了S参数仿真的核心原理、DCFEED模块的正确配置、参数扫描的设置技巧,并探讨了集成SPICE模型进行精确仿真的方法,帮助射频工程师高效、准确地获取器件关键特性。

weixin_29237635的博客 529

因内存不足原因导致fragment空白解决方案

在androidx之前,一般我们防止Fragment重建是在actvitity的onCreate方法中使用savedInstanceState?.remove(“android:support:fragments”)或者savedInstanceState?但是在androidx中,使用这两行代码不生效,但是看FragmentActivity中的FRAGMENT_TAG还是android:support:fragments,那为什么会不生效呢,后来点进去看发现。

qq_39431405的博客 548

java中switch实现分数段分级_Java中12个原子(Atomic)操作类实现原理分析

前言我们知道i++操作实际上是线程不安全的,因为一个i++操作分为了三步:1、获取的i的值2、执行i+13、将i+1的结果赋值给i而这三步不是一个原子操作,多线程环境下就会出现线程不安全性问题。Java从JDK 1.5开始,在java.util.concurrent.atomic包下提供了12个对应的原子类操作,让我们可以直接使用原子操作类来实现一个原子的i++操作。Java中一共提供了12个原子...

weixin_39799825的博客 282

Slow waitForAckedSeqno took 64873ms (threshold=30000ms). File being written

Slow waitForAckedSeqno took 64873ms (threshold=30000ms). File being written

zhengzaifeidelushang的博客 2011

Java原子操作类,知多少?

前文我们介绍了Java并发编程中的两个关键字:volatile和synchronized。我们也知道了volatile虽然是轻量级,但不能保证原子性,synchronized可以保证原子性,但是比较重量级。 那么有没有一种简单的、性能高的方法来保证Java的原子操作呢?答案当然是有的,本文就为大家揭秘一些在JDK1.5时期加入Java家族的成员——Atomic包。Atomic包下包含了12个类,...

K_Ohaha的博客 466

2024年厦门市第31届小学生C++信息学竞赛试题与解析(第一部分选择题1-10)

2024年厦门市第31届小学生C++信息学竞赛试题与解析(第一部分选择题1-10)

汉克老师的博客 110

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Java原子类Atomic详解

解决并发的线程安全问题有两种方式: 1、加锁 2、原子类

qq_40276626的博客 1万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Atomic原子类及原理

一、引入 原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作是原子操作。再比如:a++;这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。 但是,像i++这种非原子操...

奋进的小白粥 5698

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

淘宝Java面试被问:Atomic原子类的实现原理

摘要:Atomic原子类基于CAS(Compare-And-Swap)实现无锁并发,通过CPU级原子指令和volatile保证可见性。核心机制包括:1)Unsafe类提供硬件级CAS操作;2)原子类家族(基础类、数组类、引用类等)满足不同场景;3)AtomicStampedReference解决ABA问题。JDK8+增强包括LongAdder分段累加和函数式更新。使用时需注意:高竞争场景选LongAdder,复杂操作仍需锁,避免伪共享和过度创建对象。Atomic结合CAS+volatile+Unsafe成为

x2277659985的博客 1480

JUC 包中的 Atomic 原子类总结

Atomic翻译成中文是“原子”的意思。在化学上,原子是构成物质的最小单位,在化学反应中不可分割。在编程中,Atomic指的是一个操作具有原子性,即该操作不可分割、不可中断。即使在多个线程同时执行时,该操作要么全部执行完成,要么不执行,不会被其他线程看到部分完成的状态。原子类简单来说就是具有原子性操作特征的类。包中的Atomic原子类提供了一种线程安全的方式来操作单个变量。Atomic类依赖于 CAS(Compare-And-Swap,比较并交换)乐观锁来保证其方法的原子性,而不需要使用传统的锁机制(如。

double222222的博客 2498

Atomic原子类总结

这里 Atomic 是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。所以,所谓原子类说简单点就是具有原子/原子操作特征的类。

weixin_69252724的博客 1224

JUC多线程:Atomic原子类与CAS原理

tomic 原子操作类是基于无锁 CAS + volatile 实现的,并且类中的所有方法都使用 final 修饰,进一步保证线程安全。而 CAS 算法的具体实现方式在于 Unsafe 类中,Unsafe 类的所有方法都是 native 修饰的,也就是说所有方法都是直接调用操作系统底层资源进行执行相应任务。Atomic 使用乐观策略,每次操作时都假设没有冲突发生,并采用 volatile 配合 CAS 去修改内存中的变量,如果失败则重试,直到成功为止。

张维鹏的博客 9966

Java之Atomic 原子类总结

AtomicLong原理:CAS+自旋场景:低并发下的全局计算,AtomicLong能保证并发情况下计数的准确性,其内部通过CAS来解决并发安全性问题缺陷:高并发后性能急剧下降----AtomicLong的自旋会成为瓶颈(N个线程CAS操作修改线程的值,每次只有一个成功过,其他N-1失败,失败的不停自旋直至成功,这样大量失败自旋的情况,一下子cpu就打高了)LongAdder原理:CAS+Base+Cell数组分散-----空间换时间并分散了热点数据场景:高并发下的全局计算。

qq_62592925的博客 1139

JDK 中 Atomic 开头的类实现原子性的原理是什么?

JDK 中 Atomic 开头的类实现原子性的原理是什么? JDK Atomic开头的类,是通过 CAS 原理解决并发情况下原子性问题。 CAS 包含 3 个参数,CAS(V, E, N)。V 表示需要更新的变量,E 表示变量当前期望值,N 表示更新为的值。只有当变量 V 的值等于 E 时,变量 V 的值才会被更新为 N。如果变量 V 的值不等于 E ,说明变量 V 的值已经被更新...

ConstXiong 5701

JUC-Atomic原子类

java的并发包【JUC】下面就两个子包,一个是lock锁,另一个就是atomic原子包。基本类型的原子类:AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference等数组的原子类:AtomicIntegerArray、AtomicLongArray支持更高并发的原子类:LongAdder、DoubleAdder在学习之前,我们通过上述发现,为什么没有对浮点数提供原子类,如AtomicFloat、AtomicDouble?

m0_50149847的博客 1282
上一篇: 万字总结:InnoDB锁类型及其详细分析
下一篇: CTO说:Service层的接口是不是多此一举
JavaShark
博客等级 码龄4年 184粉丝 438原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值