【JUC系列第二篇】-原子变量

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。如需授权请联系微信:878799579 https://blog.csdn.net/qq_878799579/article/details/85636105 作者:毕来生微信:8787995791、什么是原子变量?​ 原子变量保证了该变量的所有操作都是原子的,不会因为多线程的同时访问而导致脏数据的读取问题。
版权声明:本文为博主原创文章,未经博主允许不得转载。如需授权请联系微信:878799579 https://blog.csdn.net/qq_878799579/article/details/85636105

作者:毕来生
微信:878799579


1、什么是原子变量?

​ 原子变量保证了该变量的所有操作都是原子的,不会因为多线程的同时访问而导致脏数据的读取问题。

2、通过synchronized保证原子操作

  1. 获取锁对象
  2. 获取失败/获取不到 ->阻塞队列等待
  3. 释放锁对象

3、Atomic之AtomicInteger源码分析

java.util.concurrent.atomic包下帮助我们提供了很多原子性的支持,请参考下图

在这里插入图片描述

  • AtomicInteger和AtomicIntegerArray:基于Integer类型

  • AtomicBoolean:基于Boolean类型

  • AtomicLong和AtomicLongArray:基于Long类型

  • AtomicReference和AtomicReferenceArray:基于引用类型


    构造方法如下

        private volatile int value;
    
        /**
         * Creates a new AtomicInteger with the given initial value.
         *
         * @param initialValue the initial value
         */
        public AtomicInteger(int initialValue) {
            value = initialValue;
        }
    
        /**
         * Creates a new AtomicInteger with initial value {@code 0}.
         */
        public AtomicInteger() {
        }
    

    如果通过构造方法设置原子变量。如不设置初始值则会默认初始化为0。

    以下为方法为AtomicInteger基于原子操作常用方法

    //获取当前原子变量中的值并为其设置新值
    public final int getAndSet(int newValue)
    
    //比较当前的value是否等于expect,如果是设置为update并返回true,否则返回false
    public final boolean compareAndSet(int expect, int update)
    
    //获取当前的value值并自增一
    public final int getAndIncrement()
    
    //获取当前的value值并自减一
    public final int getAndDecrement()
    
    //获取当前的value值并为value加上delta
    public final int getAndAdd(int delta)
    

4、实战演练

在多线程下。我希望对num = 0;进行自增,10个线程,每个线程对变量自增10000次。结果应该是100000才对。

首先我们先来一个错误示范:

package org.bilaisheng.juc;

/**
 * @Author: bilaisheng
 * @Wechat: 878799579
 * @Date: 2019/1/1 21:58
 * @Todo: AtomicInteger 原子性错误示范。仅演示使用
 * @Version : JDK11 , IDEA2018
 */
public class AtomicIntegerErrorTest {

	// 举例10条线程并发,实际条数请参考自己场景
	private static final int THREAD_COUNT = 10;

	private static int num = 0;

	public static void main(String[] args) {

		Thread[] threads = new Thread[THREAD_COUNT];

		for (int i = 0; i < THREAD_COUNT; i++) {
			threads[i] = new Thread(new Runnable() {
				@Override
				public void run() {
					// 此处设置10000.太小看不到效果。请酌情设置
					for (int j = 1; j <=10000 ; j++) {
						// 如想要看到结果请放开下行注释
						//System.out.println(Thread.currentThread().getName() +" num = "+num);
						num++ ;
					}
				}
			});
			threads[i].start();
		}

		System.out.println(Thread.currentThread().getName());
		System.out.println(Thread.activeCount());

		while (Thread.activeCount()>2){
			Thread.yield();
		}

		System.out.println(num);
	}

}

运行结果举例两张如下图所示。每次运行结果都不相同

在这里插入图片描述

在这里插入图片描述

接下来我们的AtomicInteger就该登场了

package org.bilaisheng.juc;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: bilaisheng
 * @Wechat: 878799579
 * @Date: 2019/1/1 23:02
 * @Todo:
 * @Version : JDK11 , IDEA2018
 */
public class AtomicIntegerTest {


	private static final int THREADS_CONUT = 10;
	public static AtomicInteger num = new AtomicInteger(0);


	public static void main(String[] args) {
		Thread[] threads = new Thread[THREADS_CONUT];

		for (int i = 0; i < threads.length; i++) {
			threads[i] = new Thread(new Runnable() {
				@Override
				public void run() {
					// 此处设置10000.太小看不到效果。请酌情设置
					for (int j = 1; j <=10000 ; j++) {
						// 如想要看到结果请放开下行注释
						//System.out.println(Thread.currentThread().getName() +" num = "+num);
						num.incrementAndGet();
					}
				}
			});
			threads[i].start();
		}

		while (Thread.activeCount() > 2) {
			Thread.yield();
		}
		System.out.println(num);
	}
}

结果是不管怎么运行结果都和预期下相同。运行结果如下图:

在这里插入图片描述

5、 Volatile可以保证变量原子性吗?

​ 我们先来看一下下面两行代码

private volatile long num = 4642761357212574643L;

private volatile double amt= 4642761357212574643.23165421354;

如上代码并不能保证num以及amt两个变量就是原子性的,在32位处理器中 哪怕是通过volatile关键字进行修饰也无法保证变量原子性。因为在32位系统下。如果出现了多线程同时操作某个变量。这个变量正在被线程a进行修改。此时线程b访问此变量。可能只获取到该变量的前32位,故可能会导致原子性失效。导致不可预知的情况以及错误。如果本地和生产均为64位处理器。请忽略以上废话。

目录
相关文章
|
小程序 JavaScript
在使用微信小程序开发中用vant2框架中的Uploader 文件上传wx.uploadFile无反应和使用多图上传
网上有的说是bind:after-read="afterRead"的命名问题不支持-,但是我这儿执行了console.log("file",file);证明函数运行了。后来发现是multiple="true"原因开启了多图上传,如果是多图上传的话file就是数组了
1074 2
|
5天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
5986 8
|
3天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
1093 3
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
17天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
3275 10
|
4天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
590 2
|
16天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1834 8
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
|
12天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)
1287 1

热门文章

最新文章