并发编程Atomic详解

简单来说就是原子类来实现CAS无锁模式的算法
java.util.concurrent.atomic包:是原子类的小工具包,支持在单个变量上解除锁的线程安全编程
原子变量类相当于一种泛化的 volatile 变量,能够支持原子的和有条件的读-改-写操作。
比如:AtomicInteger 表示一个int类型的值,并提供了 get 和 set 方法,这些 Volatile 类型的int
变量在读取和写入上有着相同的内存语义。它还提供了一个原子的 compareAndSet 方法(如果该
方法成功执行,那么将实现与读取/写入一个 volatile 变量相同的内存效果),以及原子的添加、
递增和递减等方法。AtomicInteger 表面上非常像一个扩展的 Counter 类,但在发生竞争的情况
下能提供更高的可伸缩性,因为它直接利用了硬件对并发的支持。
在 Java 中,java.util.concurrent.atomic 包提供了一系列原子类,旨在提供高效的线程安全操作。这些类使用了底层的 CAS(Compare-And-Swap)机制,允许多线程并发操作而不需要显式的同步。以下是对常见原子类的详细介绍,包括它们的使用场景、方法和底层机制
Atomic包中的类基本的特性就是在多线程环境下,当有多个线程同时对单个(包括基本类型及引 用类型)变量进行操作时,具有排他性,即当多个线程同时对该变量的值进行更新时,仅有一个线程能成功,而未成功的线程可以向自旋锁一样,继续尝试,一直等到执行成功。

原子类的常用类

AtomicBoolean
AtomicInteger
AtomicLong
AtomicReference
Java 的 java.util.concurrent.atomic 包提供了一系列的原子类,用于实现无锁的线程安全操作。以下是常用的原子类及其区别:
常用的原子类
AtomicBoolean:
用于对 boolean 类型的变量进行原子操作。
常用于状态标志。
AtomicInteger:
用于对 int 类型的变量进行原子操作。
提供了原子递增、递减、加法等操作。
常用于计数器、并发 ID 生成器等。
AtomicLong:
用于对 long 类型的变量进行原子操作。
提供了与 AtomicInteger 类似的方法,只是操作的变量类型是 long。
AtomicReference:
用于对对象引用进行原子操作。
可以保存任意类型的对象引用。
AtomicStampedReference:
用于解决 AtomicReference 的 ABA 问题,通过给对象引用加上一个版本号(stamp)。
常用于需要检测对象是否发生过变化的场景。
AtomicMarkableReference:
类似于 AtomicStampedReference,但使用布尔标记而不是版本号。
适用于标记对象状态的场景。
AtomicIntegerArray:
用于对 int 数组的元素进行原子操作。
每个元素都可以独立地进行原子更新。
AtomicLongArray:
用于对 long 数组的元素进行原子操作。
提供了与 AtomicIntegerArray 类似的方法。
AtomicReferenceArray:
用于对对象数组的元素进行原子操作。
可以保存任意类型的对象引用数组。
区别
数据类型:
AtomicBoolean 处理 boolean 类型的变量。
AtomicInteger 处理 int 类型的变量。
AtomicLong 处理 long 类型的变量。
AtomicReference 处理任意类型的对象引用。
AtomicStampedReference 和 AtomicMarkableReference 处理对象引用并附带版本号或标记。
AtomicIntegerArray、AtomicLongArray 和 AtomicReferenceArray 处理数组元素。
使用场景:
AtomicBoolean 常用于状态标志。
AtomicInteger 和 AtomicLong 常用于计数器、ID 生成器等。
AtomicReference 常用于需要原子更新引用的场景。
AtomicStampedReference 和 AtomicMarkableReference 用于解决 ABA 问题或标记对象状态。
AtomicIntegerArray、AtomicLongArray 和 AtomicReferenceArray 用于需要对数组元素进行原子操作的场景。
示例代码
AtomicBoolean 示例

import java.util.concurrent.atomic.AtomicBoolean;

public class Task {
    private AtomicBoolean running = new AtomicBoolean(false);

    public void start() {
        if (running.compareAndSet(false, true)) {
            new Thread(this::run).start();
        }
    }

    private void run() {
        while (running.get()) {
            // 执行任务
        }
    }

    public void stop() {
        running.set(false);
    }
}

AtomicInteger 示例

import java.util.concurrent.atomic.AtomicInteger;

public class Counter {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}

AtomicReference 示例

import java.util.concurrent.atomic.AtomicReference;

public class AtomicReferenceExample {
    private static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    private AtomicReference<Node> head = new AtomicReference<>();

    public void push(int value) {
        Node newNode = new Node(value);
        Node oldHead;
        do {
            oldHead = head.get();
            newNode.next = oldHead;
        } while (!head.compareAndSet(oldHead, newNode));
    }

    public int pop() {
        Node oldHead;
        Node newHead;
        do {
            oldHead = head.get();
            if (oldHead == null) {
                throw new RuntimeException("Stack is empty");
            }
            newHead = oldHead.next;
        } while (!head.compareAndSet(oldHead, newHead));
        return oldHead.value;
    }
}

AtomicStampedReference 示例

import java.util.concurrent.atomic.AtomicStampedReference;

public class AtomicStampedReferenceExample {
    private AtomicStampedReference<Integer> stampedRef = new AtomicStampedReference<>(0, 0);

    public void update(int newValue) {
        int[] stampHolder = new int[1];
        Integer oldValue;
        do {
            oldValue = stampedRef.get(stampHolder);
        } while (!stampedRef.compareAndSet(oldValue, newValue, stampHolder[0], stampHolder[0] + 1));
    }
}

java.util.concurrent.atomic 包中的原子类提供了多种无锁的线程安全操作方式,适用于不同类型的数据和场景。选择适当的原子类可以帮助开发者编写高效且正确的并发程序。理解各个原子类的使用场景和区别,有助于在实际开发中灵活应用这些工具。

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

思静语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值