Java并发编程——AtomicReference,解决并发修改多个属性

说到CAS理论,在java中我们第一个就想到了atomic类,一般常见的有AtomicInteger、AtomicBoolean等java.util.concurrent包下面的类,但是这个只能并发修改一个属性,如果我需要对多个属性同时进行并发修改,并且保证原子性呢?

AtomicReference 了解下?

AtomicReference也是java.util.concurrent包下的类,跟AtomicInteger等是一样的,也是基于CAS无锁理论实现的,但是不同的是 AtomicReference 是操控多个属性的原子性的并发类

在看看如何使用之前,我们先来介绍一个方法:

    public final boolean compareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
    }

官方的解释是:

Atomically sets the value to the given updated value

主要的作用是通过比对两个对象,然后更新为新的对象

这里需要注意下,这里的比对两个对象,比对的方式不是equals而是==,意味着比对的是内存的中地址,这个我们可以通过unsafe.compareAndSwapObject()方法查看,他是一个native方法

了解了上面的方法,我们来看下AtomicReference是如何使用的

模拟一个场景,在高并发的场景中,根据业务的需要,要求同时更新sequence和timestamp

    /**
     * Copyright © 2018 五月工作室. All rights reserved.
     *
     * @Project: tools
     * @ClassName: AtomicReferenceDemo
     * @Package: com.amos.tools.common.bean
     * @author: zhuqb
     * @Description: 主要用来展示AtomicReference使用方法
     * @date: 2019/9/11 0011 上午 9:46
     * @Version: V1.0
     */
    public class AtomicReferenceDemo {
    
        private Reference reference;
    
        private AtomicReference<Reference> atomicReference;
    
        /**
         * 构建器中初始化AtomicReference
         *
         * @param reference
         */
        public AtomicReferenceDemo(Reference reference) {
            this.reference = reference;
            this.atomicReference = new AtomicReference<>(reference);
        }
    
        public void atomic(Reference reference) {
            Reference referenceOld;
            Reference referenceNew;
    
            long sequence;
            long timestamp;
    
            while (true) {
                referenceOld = this.atomicReference.get();
                sequence = referenceOld.getSequence();
                sequence++;
                timestamp = System.currentTimeMillis();
    
                referenceNew = new Reference(sequence, timestamp);
                /**
                 * 比较交换
                 */
                if (this.atomicReference.compareAndSet(referenceOld, referenceNew)) {
                    reference.setSequence(sequence);
                    reference.setTimestamp(timestamp);
                    break;
                }
            }
        }
    }
    
    /**
     * 业务场景模拟
     * 序列需要自增并且时间需要更新成最新的时间戳
     */
    @Data
    @AllArgsConstructor
    class Reference {
        /**
         * 序列
         */
        private long sequence;
        /**
         * 时间戳
         */
        private long timestamp;
    }

上述代码的逻辑如下:

  • 获取并缓存原来的变量,这个变量包含原来的序列和时间戳
  • 基于原来的变量来更新新的时间戳和序列
  • 计算后,使用CAS操作更新原来的变量,更新的过程中,需要传递保存原来的变量
  • 如果保存的原来变量被其他线程修改了,就需要在这里重新拿到最新的变量,并再次计算和重试更新
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
├─第一阶段 │      源码+ppt.rar │      高并发编程第一阶段01讲、课程大纲及主要内容介绍.wmv │      高并发编程第一阶段02讲、简单介绍什么是线程.wmv │      高并发编程第一阶段03讲、创建并启动线程.mp4 │      高并发编程第一阶段04讲、线程生命周期以及start方法源码剖析.mp4 │      高并发编程第一阶段05讲、采用多线程方式模拟银行排队叫号.mp4 │      高并发编程第一阶段06讲、用Runnable接口将线程的逻辑执行单元从控制中抽取出来.mp4 │      高并发编程第一阶段07讲、策略模式在Thread和Runnable中的应用分析.mp4 │      高并发编程第一阶段08讲、构造Thread对象你也许不知道的几件事.mp4 │      高并发编程第一阶段09讲、多线程与JVM内存结构的关系,虚拟机栈实验.mp4 │      高并发编程第一阶段10讲、Thread构造函数StackSize详细讲解.mp4 │      高并发编程第一阶段11讲、Thread构造函数StackSize详细讲解-续.mp4 │      高并发编程第一阶段12讲、Daemon线程的创建以及使用场景分析.mp4 │      高并发编程第一阶段13讲、线程ID,优先级讲解.mp4 │      高并发编程第一阶段14讲、Thread的join方法详细介绍,结合一个典型案例.mp4 │      高并发编程第一阶段15讲、Thread中断Interrupt方法详细讲解.mp4 │      高并发编程第一阶段16讲、采用优雅的方式结束线程生命周期.mp4 │      高并发编程第一阶段17讲、Thread API综合实战,编写ThreadService实现暴力结束线程的综合实战.mp4 │      高并发编程第一阶段18讲、数据同步的引入与Synchronized的简单介绍.mp4 │      高并发编程第一阶段19讲、结合jconsole,jstack以及汇编指令认识synchronized关键字.mp4 │      高并发编程第一阶段20讲、同步代码块以及同步方法之间的区别和关系.mp4 │      高并发编程第一阶段21讲、通过实验分析This锁的存在.mp4 │      高并发编程第一阶段22讲、通过实验分析Class锁的存在.mp4 │      高并发编程第一阶段23讲、多线程死锁分析,案例介绍.mp4 │      高并发编程第一阶段24讲、线程间通信快速入门,使用wait和notify进行线程间的数据通信.mp4 │      高并发编程第一阶段25讲、多Produce多Consume之间的通讯导致出现程序假死的原因分析.mp4 │      高并发编程第一阶段26讲、多线程下的生产者消费者模型,以及详细介绍notifyAll方法.mp4 │      高并发编程第一阶段27讲、wait和sleep的本质区别是什么,深入分析(面试常见问题).mp4 │      高并发编程第一阶段28讲、线程生产者消费者的综合实战结合Java8语法.mp4 │      高并发编程第一阶段29讲、如何实现一个自己的显式锁Lock精讲上.mp4 │      高并发编程第一阶段30讲、如何实现一个自己的显式锁Lock精讲下(让锁具备超时功能).mp4 │      高并发编程第一阶段31讲、如何给你的应用程序注入钩子程序,Linux下演示.mp4 │      高并发编程第一阶段32讲、如何捕获线程运行期间的异常.mp4 │      高并发编程第一阶段33讲、ThreadGroup API介绍之一.mp4 │      高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │      高并发编程第一阶段35讲、线程池原理与自定义线程池.mp4 │      高并发编程第一阶段36讲、自定义个简单的线程池并且测试.mp4 │      高并发编程第一阶段37讲、给线程池增加拒绝策略以及停止方法.mp4 │      高并发编程第一阶段38讲、给线程池增加自动扩充线程数量,以及闲时自动回收的功能.mp4 │      高并发编程第一阶段39讲、课程结束,内容回顾,下季内容预告.mp4 │ ├─第二阶段 │       Java并发编程.png │       ppt+源码.rar │       高并发编程第二阶段01讲、课程大纲及主要内容介绍.wmv │       高并发编程第二阶段02讲、介绍四种Singleton方式的优缺点在多线程情况下.wmv │       高并发编程第二阶段03讲、介绍三种高效优雅的Singleto

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值