前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【JUC基础】10. Atomic原子类

【JUC基础】10. Atomic原子类

作者头像
有一只柴犬
发布2024-01-25 11:03:26
1250
发布2024-01-25 11:03:26
举报
文章被收录于专栏:JAVA体系

1、什么是Atomic

Atomic英译为原子的。原子结构通常称为不可分割的最小单位。而在JUC中,java.util.concurrent.atomic 包是 Java 并发库中的一个包,提供了原子操作的支持。它包含了一些原子类,用于在多线程环境下进行线程安全的原子操作。使用原子类可以避免使用锁和同步机制,从而减少了线程竞争和死锁的风险,并提高了多线程程序的性能和可伸缩性。

2、为什么要使用Atomic

这里是JUC专栏,肯定是跟多线程有关系的。我们实现这样一个场景:2个线程对某个数值+1操作,每个线程累加10000次。

2.1、传统模式

代码语言:javascript
复制
package atomic;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Shamee loop
 * @date 2023/5/22
 */
public class AtomicTest {

    private static int counter = 0;
    public static void main(String[] args) {
        // 多个线程并发地增加计数器的值
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                counter++;
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                counter++;
            }
        });

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();

        System.out.println("Counter value: " + counter);
    }
}

执行结果:

不管运行多少次,每次的结果都不一样,而且最终的值大概率都不会是20000。而20000才是我们期望的输出。

2.2、原子模式

代码语言:javascript
复制
package atomic;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Shamee loop
 * @date 2023/5/22
 */
public class AtomicTest {

    // 原子性int
    private static AtomicInteger counter = new AtomicInteger(0);

    public static void main(String[] args) {
        // 多个线程并发地增加计数器的值
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                // 等同于++操作
                counter.incrementAndGet();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                counter.incrementAndGet();
            }
        });

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();

        System.out.println("Counter value: " + counter.get());
    }
}

运行结果:

不管运行多少次,结果都是20000。可以看出代码中不需要加任何锁,Atomic在多线程场合天然的具备线程安全。

3、原子类

java.util.concurrent.atomic包下常用的原子类分为:

3.1、原子基本类型

  • AtomicInteger:整形原子类
  • AtomicLong:长整型原子类
  • AtomicBoolean :布尔型原子类

3.2、原子引用类型

  • AtomicReference:引用类型原子类

3.3、原子数组类

  • AtomicIntegerArray:整形数组原子类
  • AtomicLongArray:长整形数组原子类
  • AtomicReferenceArray :引用类型数组原子类

......

4、原子类是绝对线程安全吗?

首先,什么是线程安全问题? 在多线程编程中,线程安全是指多个线程同时访问一个共享资源时,不会产生不正确的结果或破坏数据结构的属性。

其实Atomic的原子性是指属性的存取(get/set)方法是线程安全,他的线程安全保证并不是简单的使用synchronized或lock锁。而是使用了乐观锁CAS(Compare And Swap,比较并交换)+volatile。关于CAS,可以参考《简单理解CAS》。正如CAS锁的ABA问题,它并不能保证对象是线程安全的。

因此Atomic并不是绝对的线程安全。

在多线程编程中,"atomic"操作通常被认为是一种细粒度的同步机制,用于保护共享数据的访问和修改。它们通常比其他同步机制(如锁)的开销更小,并且可以提供一定程度的线程安全性。

"atomic"操作的行为因编程语言和上下文而异,以下是一些常见情况和注意事项:

  1. 原子读取(Atomic Reads):"atomic"操作可以确保从共享变量中读取的值是最新的。这意味着一个线程在读取共享变量时,不会看到另一个线程修改变量后的旧值。
  2. 原子写入(Atomic Writes):"atomic"操作可以确保将值写入共享变量时的原子性。这意味着一个线程在写入共享变量时,不会被其他线程的读取或写入操作中断或干扰。
  3. 原子递增和递减(Atomic Increment/Decrement):某些编程语言提供原子递增和递减操作,以确保对共享计数器的操作是线程安全的。这些操作会在执行过程中阻止其他线程的干扰。

尽管"atomic"操作提供了一定的线程安全性,但在处理复杂的并发场景时,仍然需要考虑其他因素,如数据竞争、同步机制的选择和使用正确的内存模型等。此外,"atomic"操作并不能解决所有的线程安全问题,如死锁、竞争条件等。

因此,如果在特定的编程语言或框架中使用"atomic"操作,建议查阅相关文档和规范,以了解其具体行为和适用范围。同时,仍然需要谨慎设计和编写多线程代码,以确保整个程序的线程安全性。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、什么是Atomic
  • 2、为什么要使用Atomic
    • 2.1、传统模式
      • 2.2、原子模式
      • 3、原子类
        • 3.1、原子基本类型
          • 3.2、原子引用类型
            • 3.3、原子数组类
            • 4、原子类是绝对线程安全吗?
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档