JUC之CAS和原子操作类

news2024/10/6 8:31:57

文章目录

  • 1 CAS
    • 1.1 是什么
    • 1.2 原理
    • 1.3 UnSafe
    • 1.4 自旋锁
    • 1.5 CAS的问题
      • 1.5.1 死循环消耗CPU资源
      • 1.5.2 ABA问题
  • 2 原子操作类
    • 2.1 引用类型原子类
      • 2.1.1 AtomicReference
      • 2.1.2 AtomicStampedReference
      • 2.1.3 AtomicMarkableReference
    • 2.2 基本类型原子类
    • 2.3 数组类型原子类
    • 2.4 对象的属性修改原子类
      • 2.4.1 使用目的
      • 2.4.2 使用要求
      • 2.4.3 AtomicIntegerFieldUpdater使用Demo
      • 2.4.4 AtomicReferenceFieldUpdater使用Demo

1 CAS

1.1 是什么

在这里插入图片描述
在这里插入图片描述

1.2 原理

在这里插入图片描述
在这里插入图片描述

1.3 UnSafe

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.4 自旋锁

在这里插入图片描述

1.5 CAS的问题

1.5.1 死循环消耗CPU资源

1.5.2 ABA问题

在这里插入图片描述
很形象的两个例子:

  1. 隔壁老王动了你GF,但是又回复了原样。你能认为这件事情没有发生过么?
  2. 挪用公款然后抹平了亏空。

【问题解决】
版本号和戳记流水机制。

2 原子操作类

2.1 引用类型原子类

2.1.1 AtomicReference

AtomicReference<Phone> atomicPhone = new AtomicReference<>();

2.1.2 AtomicStampedReference

在这里插入图片描述

2.1.3 AtomicMarkableReference

在这里插入图片描述

2.2 基本类型原子类

通过一个demo来了解AtomicInteger的使用。

package org.example.atomicnum;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

class Number {
    AtomicInteger number = new AtomicInteger();

    public void increment() {
        number.getAndIncrement();
    }
}

public class Demo {
    private static int SIZE = 50;

    private static Number myNumber = new Number();

    private static CountDownLatch countDownLatch = new CountDownLatch(SIZE);

    public static void main(String[] args) {
        for (int i = 0; i < SIZE; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        for (int j = 1; j <= 1000; j++) {
                            myNumber.increment();
                        }
                    } finally {
                        countDownLatch.countDown();
                    }
                }
            }, String.valueOf(i)).start();
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

		// 如果没有使用CountDownLatch,很可能main thread查早了,查出来的结果不对。 
        System.out.println("main thread: the result = " + myNumber.number.get());
    }
}

2.3 数组类型原子类

2.4 对象的属性修改原子类

2.4.1 使用目的

以一种线程安全的方式操作非线程安全对象内的某些字段。

2.4.2 使用要求

  1. 更新的对象属性必须使用public volatile进行修饰
  2. 因为属性修改原子类都是抽象类,所以必须使用静态方法newUpdater()来创建更新器实例,并且设置想要更新的类和属性。

2.4.3 AtomicIntegerFieldUpdater使用Demo

package org.example.atomicfieldupdater;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

public class BankAccount {
    String bankName = "CCB";

    public volatile int money = 0;

    private static AtomicIntegerFieldUpdater moneyUpdater =
        AtomicIntegerFieldUpdater.newUpdater(BankAccount.class, "money");

    /**
     * 局部微创小手术
     *
     * @param bankAccount
     */
    public static void transfer(BankAccount bankAccount) {
        moneyUpdater.getAndIncrement(bankAccount);
    }
}

package org.example.atomicfieldupdater;

import java.util.concurrent.CountDownLatch;

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        BankAccount bankAccount = new BankAccount();

        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        for (int j = 0; j < 1000; j++) {
                            BankAccount.transfer(bankAccount);
                        }
                    } finally {
                        countDownLatch.countDown();
                    }

                }
            }).start();
        }

        countDownLatch.await();

        System.out.println("money = " + bankAccount.money);
    }
}

2.4.4 AtomicReferenceFieldUpdater使用Demo

package org.example.atomicfieldupdater;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

class MyVar {
    public volatile Boolean isInit = Boolean.FALSE;

    private static AtomicReferenceFieldUpdater<MyVar, Boolean> initUpdater =
        AtomicReferenceFieldUpdater.newUpdater(MyVar.class, Boolean.class, "isInit");

    public static void init(MyVar myVar) {
        if (initUpdater.compareAndSet(myVar, Boolean.FALSE, Boolean.TRUE)) {
            System.out.println(Thread.currentThread().getName() + "\t" + "start init, need 2 seconds.");
            sleepSeconds(2);
            System.out.println(Thread.currentThread().getName() + "\t" + "init over.");
        } else {
            System.out.println(Thread.currentThread().getName() + "\t" + "Other thread executing init work.");
        }
    }

    private static void sleepSeconds(int seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

public class Demo2 {
    public static void main(String[] args) {
        MyVar myVar = new MyVar();

        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                MyVar.init(myVar);
            }, String.valueOf(i)).start();
        }
    }
}

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

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

相关文章

【2022 JCR 期刊影响因子】(四)水资源

原文链接&#xff1a; 【2022 JCR 期刊影响因子】&#xff08;四&#xff09;水资源 微信公众号同步更新 地信学子GISer and Coder 2022 JCR 期刊影响因子刚刚发布&#xff0c;今年的影响因子只保留1位小数。水资源领域的 SCIE 收录期刊的影响因子如下。 微信公众号同步更新 …

Unity基础-Vector3.Lerp的使用给一个简单的实例

一个简单的实例&#xff0c;演示了如何使用Vector3.Lerp来实现物体在两个位置之间平滑移动的效果&#xff1a; using UnityEngine;public class ObjectMovement : MonoBehaviour {public Transform startPoint;public Transform endPoint;public float moveDuration 2f;priva…

[PMLR 2021] Zero-Shot Text-to-Image Generation:零样本文本到图像生成

[PMLR 2021]Zero-Shot Text-to-Image Generation&#xff1a;零样本文本到图像生成 Fig 1. 原始图像(上)和离散VAE重建图像(下)的比较。编码器对空间分辨率进行8倍的下采样。虽然细节(例如&#xff0c;猫毛的纹理、店面上的文字和插图中的细线)有时会丢失或扭曲&#xff0c;但图…

为什么有些前端一直用 div 当按钮,而不是用 button?

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言div 和 button使用…

Linux学习之进程控制和进程之间的关系

nice值的设定 关于vim四种模式一些介绍&#xff0c;可以看《Linux学习之vim正常模式和插入模式》 vim a.sh&#xff0c;按i进入到插入模式&#xff0c;这样才能输入字符到a.sh文件中。 把下边的内容写进去&#xff1a; #!/bin/bashecho $$ while : # 无限循环 do: done按Es…

Redis设计与实现笔记之SDS

1 数据结构与对象 1.1 简单动态字符串 SDS简单动态字符串&#xff08;simple dynamic string&#xff0c;SDS&#xff09;是Redis中字符串的底层数据结构。 struct sdshdr {// 记录 buf 数组中已使用字节的数量// 等于 SDS 所保存字符串的长度int len;// 记录 buf 数组中未使…

房屋信息怎么做二维码?户型文件怎么批量转二维码?

现在很多房产开发商都会用二维码来储存各个楼每户的信息&#xff0c;可能是建筑平面图、验房信息、楼区信息等等。那么如果将每户信息导出单独的文件之后&#xff0c;怎样才能够将每个文件批量转成二维码呢&#xff1f;下面教大家使用二维码生成器&#xff08;免费在线二维码生…

pytorch快速入门中文——07(TensorBoard)

使用 TensorBoard 可视化模型&#xff0c;数据和训练 原文&#xff1a;https://pytorch.org/tutorials/intermediate/tensorboard_tutorial.html 在 60 分钟突击中&#xff0c;我们向您展示了如何加载数据&#xff0c;如何通过定义为nn.Module子类的模型提供数据&#xff0c;如…

HTTP协议、存储、Ajax

HTTP协议、存储、Ajax 前端数据交互与HTTP协议 前后端通信 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>初识前后端通信</title></head><body><script>// 1.前后端通信…

手术麻醉临床信息系统源码:实现手术全流程自动化和信息化

手术麻醉临床信息系统遵循“以病人为中心、服务于临床”的宗旨&#xff0c;使医护人员从繁琐的病历书写中解放出来&#xff0c;集中精力关注病人的诊疗&#xff0c;将更多的时间用于分析、诊断。以服务围术期临床业务工作的开展为核心&#xff0c;为医护人员、业务管理人员、院…

APP外包开发闪退解决工具

APP上线后出现闪退问题往往不好解决&#xff0c;解决这些问题耗时耗力&#xff0c;但解决好了会对用户体验有非常大的帮助。今天和大家分享解决APP闪退问题的一般流程&#xff0c;但具体情况可能会因为问题的复杂性和具体情况有所不同。北京木奇移动技术有限公司&#xff0c;专…

机器学习李宏毅学习笔记34

文章目录 前言一、Knowledge distillation二、Parameter quantization三、Architecture design四、Dynamic computation总结 前言 神经网络压缩&#xff08;二&#xff09;其他方法 一、Knowledge distillation 先train一个大的network叫做teacher network&#xff0c;小的ne…

Java微服务金融项目智牛股-基础知识二(Sentinel简介)

Sentinel 背景 微服务架构设计由众多为服务组成&#xff0c;为保障高可用&#xff0c;通常会采用集群方式部署。由于服务自身原因或网络等其他问题&#xff0c;并不能保证100%可用性&#xff0c; 若单个服务出现问题&#xff0c; 会导致进入该服务的线程阻塞&#xff0c; 如果…

【Linux】操作系统的基本概念 {冯诺依曼体系结构,操作系统的基本概念,系统调用及用户操作接口,shell程序}

一、冯诺依曼体系结构 现代计算机设计大都遵守冯诺依曼体系结构&#xff1a; 截至目前&#xff0c;我们所认识的计算机&#xff0c;都是由一个个的硬件组件组成 输入单元&#xff1a;包括键盘, 鼠标&#xff0c;扫描仪, 磁盘&#xff0c;网卡等 存储器&#xff1a;内存&#…

cuda 安装(windows)简单

除了在linux上用&#xff0c;部分初学者也会在windows上用 需要在linux上安装的参考这篇&#xff1a;cuda linux安装 有的教程讲的很复杂&#xff0c;起始很简单 1.下载Cuda Toolkit&#xff08;全家桶&#xff09; cuda-toolkit官方页面 找到需要的版本 2.安装 双击然后下…

MySQL MHA高可用集群部署及故障切换

MySQL MHA高可用集群部署及故障切换 一、MHA概述二、MHA的组成三、MHA的特点四、MHA的原理五、搭建MySQLMHA1、所有服务器&#xff0c;关闭系统防火墙和安全机制2、修改 master&#xff08;192.168.92.11&#xff09;、Slave1&#xff08;192.168.92.12&#xff09;、Slave2&am…

使用Gradio创建交互式复选框组件

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Web (27号培训)

Get_POST Upload1 最后蚁剑链接寻找文件即可 简单的登录 用给好的字典爆破就好了 这仅仅只是爆破吗&#xff1f; 账户hacker 密码123456 1.爆破hacker帐号的密码 2.登录hacker帐号 3.抓包后将user改成vvvlllll&#xff0c;放包 4.即得flag

今日份分享:转换音频格式的软件有哪些

曾经有一位音乐爱好者&#xff0c;名叫张丽。她热爱收集高质量的音乐&#xff0c;尤其钟爱flac这种无损音频格式。然而&#xff0c;有一天&#xff0c;她遇到了一个问题&#xff1a;她的音乐播放器不支持flac格式&#xff0c;因此她迫切需要找到一种软件来转换flac音频格式。那…

助你丝滑过度到 Vue3 初识 ②②

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; VUE3~TS &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f449;…