【JUC】原子操作类

news2024/12/23 13:15:33

【JUC】原子操作类

文章目录

  • 【JUC】原子操作类
    • 1. 原子操作类
      • 1.1 基本类型原子类
      • 1.2 数组类型原子类
      • 1.3 引用类型原子类
        • 1.3.1 AtomicReference
        • 1.3.2 AtomicStampedReference
        • 1.3.3 AtomicMarkableReference
      • 1.4 对象的属性修改原子类

1. 原子操作类

原子操作类如下所示:

  1. AtomicBoolean
  2. AtomicInteger
  3. AtomicIntegerArray
  4. AtomicIntegerFieldUpdater
  5. AtomicLong
  6. AtomicLongArray
  7. AtomicLongFieldUpdater
  8. AtomicMarkableReference
  9. AtomicReference
  10. AtomicReferenceArray
  11. AtomicReferenceFieldUpdater
  12. AtomicStampedReference
  13. DoubleAccumulator
  14. DoubleAdder
  15. LongAccumulator
  16. LongAdder

根据每个类的特点可以将其分成几种不同的类型:

1.1 基本类型原子类

基本类型原子类包含以下三类:

  1. AtomicInteger
  2. AtomicBoolean
  3. AtomicLong

AtomicInteger 为例,其常用API如下(其他类也差不多):

  • public final int get() //获取当前的值
  • public final int getAndSet(int newValue)//获取当前的值,并设置新的值
  • public final int getAndIncrement()//获取当前的值,并自增
  • public final int getAndDecrement() //获取当前的值,并自减
  • public final int getAndAdd(int delta) //获取当前的值,并加上预期的值
  • boolean compareAndSet(int expect, int update) //如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update)

AtomicInteger 演示 i++

class MyNumber {
    AtomicInteger atomicInteger = new AtomicInteger();

    public void addPlusPlus() {
        atomicInteger.getAndIncrement();
    }
}

public class AtomicIntegerDemo {
    public static final int SIZE = 50;

    public static void main(String[] args) throws InterruptedException {
        MyNumber myNumber = new MyNumber();
        CountDownLatch countDownLatch = new CountDownLatch(SIZE);

        for (int i = 1; i <= SIZE; i++) {
            new Thread(() -> {
                try {
                    for (int j = 1; j <= 1000; j++) {
                        myNumber.addPlusPlus();
                    }
                } finally {
                    countDownLatch.countDown();
                }
            }, String.valueOf(i)).start();
        }
        
        //等待上面50个线程全部计算完成后,再去获得最终值
        countDownLatch.await();

        System.out.println(Thread.currentThread().getName() + "\t" + "result: " + myNumber.atomicInteger.get());
    }
}

运行结果如下:

image-20230422173820024


1.2 数组类型原子类

数组类型原子类包含以下三类:

  1. AtomicIntegerArray
  2. AtomicLongArray
  3. AtomicReferenceArray

AtomicIntegerArray 演示基本用法:

public class AtomicIntegerArrayDemo {
    public static void main(String[] args) {
        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[5]);
        //AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(5);
        //AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[]{1,2,3,4,5});

        for (int i = 0; i < atomicIntegerArray.length(); i++) {
            System.out.println(atomicIntegerArray.get(i));
        }

        System.out.println();

        int tmpInt = 0;

        tmpInt = atomicIntegerArray.getAndSet(0, 1122);
        System.out.println(tmpInt + "\t" + atomicIntegerArray.get(0));

        tmpInt = atomicIntegerArray.getAndIncrement(0);
        System.out.println(tmpInt + "\t" + atomicIntegerArray.get(0));
    }
}

运行结果如下所示:

image-20230422174509323


1.3 引用类型原子类

引用类型原子类包括以下三类:

  1. AtomicReference
  2. AtomicStampedReference
    • 携带版本号的引用类型原子类,可以解决 ABA问题
    • 解决修改过几次
    • 状态戳原子引用
  3. AtomicMarkableReference
    • 原子更新带有标记位的引用类型对象
    • 解决是否修改过(将状态戳简化为true/false)
    • 状态戳(true/false)原子引用

1.3.1 AtomicReference

AtomicReference 使用实例:

class User {
    String userName;
    int age;
}

/**
 * @auther zzyy
 * @create 2022-02-24 14:50
 */
public class AtomicReferenceDemo {
    public static void main(String[] args) {
        AtomicReference<User> atomicReference = new AtomicReference<>();

        User z3 = new User("z3", 22);
        User li4 = new User("li4", 28);

        atomicReference.set(z3);

        System.out.println(atomicReference.compareAndSet(z3, li4) + "\t" + atomicReference.get().toString());
        System.out.println(atomicReference.compareAndSet(z3, li4) + "\t" + atomicReference.get().toString());


    }
}

运行结果如下:

image-20230422211147704

使用 AtomicReference 实现一个自旋锁:

public class SpinLockDemo {
    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    public void lock() {
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + "\t" + "----come in");
        while (!atomicReference.compareAndSet(null, thread)) {

        }
    }

    public void unLock() {
        Thread thread = Thread.currentThread();
        atomicReference.compareAndSet(thread, null);
        System.out.println(Thread.currentThread().getName() + "\t" + "----task over,unLock...");
    }

    public static void main(String[] args) {
        SpinLockDemo spinLockDemo = new SpinLockDemo();

        new Thread(() -> {
            spinLockDemo.lock();
            //暂停几秒钟线程
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLockDemo.unLock();
        }, "A").start();

        //暂停500毫秒,线程A先于B启动
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            spinLockDemo.lock();

            spinLockDemo.unLock();
        }, "B").start();


    }
}

1.3.2 AtomicStampedReference

携带版本号的引用类型原子类,可以解决 ABA问题 。可以记录修改过几次变量。

示例如下:

public class ABADemo {
    static AtomicStampedReference<Integer> stampedReference = new AtomicStampedReference<>(100, 1);

    public static void main(String[] args) {
        new Thread(() -> {
            int stamp = stampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + "\t" + "首次版本号:" + stamp);

            //暂停500毫秒,保证后面的t4线程初始化拿到的版本号和我一样
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            stampedReference.compareAndSet(100, 101, stampedReference.getStamp(), stampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + "\t" + "2次流水号:" + stampedReference.getStamp());

            stampedReference.compareAndSet(101, 100, stampedReference.getStamp(), stampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + "\t" + "3次流水号:" + stampedReference.getStamp());

        }, "t3").start();

        new Thread(() -> {
            int stamp = stampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + "\t" + "首次版本号:" + stamp);

            //暂停1秒钟线程,等待上面的t3线程,发生了ABA问题
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            boolean b = stampedReference.compareAndSet(100, 2022, stamp, stamp + 1);

            System.out.println(b + "\t" + stampedReference.getReference() + "\t" + stampedReference.getStamp());

        }, "t4").start();

    }
}

运行结果如下:

image-20230422211701736


1.3.3 AtomicMarkableReference

原子更新带有标记位的引用类型对象,它的定义就算将状态戳简化为 true/false

示例代码:

public class AtomicMarkableReferenceDemo {
    static AtomicMarkableReference markableReference = new AtomicMarkableReference(100, false);

    public static void main(String[] args) {
        new Thread(() -> {
            boolean marked = markableReference.isMarked();
            System.out.println(Thread.currentThread().getName() + "\t" + "默认标识:" + marked);
            //暂停1秒钟线程,等待后面的T2线程和我拿到一样的模式flag标识,都是false
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            markableReference.compareAndSet(100, 1000, marked, !marked);
        }, "t1").start();

        new Thread(() -> {
            boolean marked = markableReference.isMarked();
            System.out.println(Thread.currentThread().getName() + "\t" + "默认标识:" + marked);

            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean b = markableReference.compareAndSet(100, 2000, marked, !marked);
            System.out.println(Thread.currentThread().getName() + "\t" + "t2线程CASresult: " + b);
            System.out.println(Thread.currentThread().getName() + "\t" + markableReference.isMarked());
            System.out.println(Thread.currentThread().getName() + "\t" + markableReference.getReference());
        }, "t2").start();
    }
}

运行结果:

image-20230422211918106


1.4 对象的属性修改原子类

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/449584.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】进程间通信 --- 管道 共享内存 消息队列 信号量

等明年国庆去西藏洗涤灵魂&#xff0c;laozi不伺候这无聊的生活了 文章目录 一、进程间通信1.什么是通信&#xff1f;&#xff08;IPC&#xff09;2.为什么要有通信&#xff1f;&#xff08;多进程协同&#xff09;3.如何进行通信&#xff1f; 二、基于文件系统的管道通信1.通信…

acwing17给了一个头节点,从尾到头输出链表的元素,顺便练练容器

方法一 建立一个数组&#xff0c;从头到尾遍历一遍链表&#xff0c;然后将链表的每个元素的值赋给数组 犯了一个错误 新建的vector容器是一个可变长的数组&#xff0c;要想像数组下标那样访问前提是这个下标所指向的元素得存在&#xff0c;这也就跟那个声明一维数组得写出长度来…

rk3568 适配摄像头 (CIF协议)

rk3568 适配摄像头 (CIF协议) 在RK3568处理器中&#xff0c;支持CIF协议的摄像头可以通过CSI接口连接到处理器&#xff0c;实现视频数据的采集和处理。同时&#xff0c;RK3568还支持多种图像处理算法和编解码器&#xff0c;可以对采集到的视频数据进行实时处理和压缩&#xff…

[Golang实战] 带你入手gin框架使用,以项目为例

&#x1f61a;一个不甘平凡的普通人&#xff0c;致力于为Golang社区和算法学习做出贡献&#xff0c;期待您的关注和认可&#xff0c;陪您一起学习打卡&#xff01;&#xff01;&#xff01;&#x1f618;&#x1f618;&#x1f618; &#x1f917;专栏&#xff1a;算法学习 &am…

Dear ImGui结合CMake实现基于GLFW和OpenGL3的入门级hello world代码

Dear ImGui结合CMake实现基于GLFW和OpenGL3的入门级hello world代码 如需转载请标明出处&#xff1a;https://blog.csdn.net/itas109 技术交流&#xff1a;129518033 环境&#xff1a; OS: windows 10 / Ubuntu 22.04 imgui: 1.89.5 glw: 3.3.8前言 Dear ImGui 是一个 用于…

alibaba arthas的新人上手教程

背景 Arthas 是Alibaba开源的Java诊断工具。 github开源地址&#xff1a;GitHub - alibaba/arthas: Alibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas 上手教程 1.下载arthas&#xff0c;并测试运行demo curl -O https://arthas.aliyun.com/arthas-boot.j…

高防IP的定义与作用

随着网络技术的发展&#xff0c;网络攻击的频率和威力不断升级&#xff0c;对企业和个人的网络安全造成了巨大风险。于是&#xff0c;高防IP作为一种网络安全防护工具应运而生&#xff0c;成为广大用户保障网络安全的重要手段。接下来让我们一起来详细了解下高防IP的定义和作用…

web实验(1)

&#xff08;1&#xff09; 应用html和css完成如图所示界面效果。内容相对于浏览器居中&#xff0c;图标见附件disc.jpg。 说明&#xff1a; 内容相对于浏览器居中&#xff0c;图标见附件disc.jpg盒子边框1px solid #ccc&#xff0c;内边距20px文本字体颜色#122e67&#xff…

outlook邮箱pc/mac客户端下载 含最新版

新的 Outlook for Windows or mac 为 Outlook 应用带来了最新功能、智能辅助功能和新的新式简化设计。 你可以根据自己的风格定制它&#xff0c;并使用新的 Outlook for Windows/mac 执行更多操作&#xff01; 览版&#xff0c;与我们一起开始旅程&#xff0c;并帮助我们塑造新…

SSM整合完整流程

&#x1f3e0;个人主页&#xff1a;shark-Gao &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是shark-Gao&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f389;目前状况&#xff1a;23届毕业生&#xff0c;目前在某公司实习&#x1f…

Django--DRf---序列化器:序列化器嵌套

模型表&#xff1a; from django.db import models# Create your models here.class StudentModel(models.Model):id models.AutoField(primary_keyTrue)name models.CharField(max_length32,verbose_name姓名)age models.SmallIntegerField(verbose_name年龄)class_mate_f…

人人可用的开源数据可视化分析工具-DataEase

DataEase 介绍 DataEase是一种开源的关系型数据库管理系统&#xff0c;旨在帮助用户创建和管理各种类型的数据。它是一种易于使用的工具&#xff0c;适用于各种规模的企业和组织&#xff0c;从个人使用到大型公司使用。 Github 地址&#xff1a;GitHub - dataease/dataease: …

2023年4月份上新的Transformer模型设计系列论文(附下载链接)

来源&#xff1a;投稿 作者&#xff1a;王老师 编辑&#xff1a;学姐 论文1 论文标题&#xff1a; Slide-Transformer: Hierarchical Vision Transformer with Local Self-Attention** 滑动Transformer&#xff1a;具有局部自注意的分层视觉Transformer 论文链接&#xff1a;h…

ChatGPT 克隆方案,开源了!开箱即用

什么是 ChatGPT ChatGPT是一种基于人工智能技术的大型语言模型&#xff0c;它能够理解和处理人类自然语言&#xff0c;并且在回答问题、生成文本和模拟对话等方面表现出色。ChatGPT使用的是GPT-3.5架构&#xff0c;它在训练过程中接触了大量的语言数据&#xff0c;并利用这些数…

机器学习算法系列(四)-- 决策树

机器学习算法之–决策树 最经典的机器学习模型之一&#xff0c;成树型结构&#xff0c;决策树的目的是为了产生一颗泛化能力强&#xff0c;处理未见实例能力强的树&#xff0c;通过特征判断不断分类&#xff0c;基本流程遵循“分而治之”的递归分类策略。 一、算法原理 1.1、特…

《C++程序设计原理与实践》笔记 第17章 向量和自由空间

本章和后面四章介绍C标准库的容器和算法部分&#xff08;通常称为STL&#xff09;。本章和后面两张的重点是最常用、最有用的STL容器——向量的设计和实现。 17.1 引言 C标准库中最有用的容器是vector。vector提供了给定类型的元素序列。标准库vector是一个方便、灵活、&…

Redis从零上手

文章目录 NoSQL概述互联网发展史单机MySQL的年代&#xff08;90年代&#xff09;缓存时代: Memcached MySQL 垂直拆分(读写分离)分库分表 水平拆分(MySQL集群)如今最近的年代 为什么要用NoSQL什么是NoSQLNoSQL特点阿里巴巴演进分析阿里巴巴中文站架构发展历程简单分析 NoSQL…

MySQL架构设计其实很简单

一、概述 我们很多互联网项目首选的数据库就是MySql5.7&#xff0c;因为免费&#xff0c;支持数据库主从复制&#xff0c;读写分离&#xff0c;且语法简单&#xff0c;容易上手&#xff0c;虽然对sql的函数、触发器、存储过程有一定的了解&#xff0c;也能说出一些优化sql语句…

基于SpringBoot+Vue的前后端分离的博客管理系统

菜单 首页写文章内容管理 博客管理相册管理归档登录、注册(项目整合了shiro+jwt+redis,用户未登录不能发布博客、内容管理、相册、归档等功能) 文章​​​​​​​末尾赋前后端代码以及数据库文件链接!!! 1 首页 首页包括菜单、博客、登录用户、推荐博客排行、博客分类…

Autosar-Interface接口

文章目录 一、Autosar接口1、AUTOSAR Interface2、Standardized Interface3、Standardized AUTOSAR Interface二、AUTOSAR接口的通用规则三、示例-存储四、总结一、Autosar接口 在Autosar里规定了三类接口,分别是AUTOSAR接口,标准AUTOSAR接口和标准接口。 下图将所有的接口…