(转)Java atomic原子类的使用方法和原理(一)

在讲atomic原子类之前先看一个小例子:

<span class="hljs-keyword">public <span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">UseAtomic {

   <span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-keyword">static <span class="hljs-keyword">void <span class="hljs-title">main<span class="hljs-params">(String[] args) {
       AtomicInteger atomicInteger=<span class="hljs-keyword">new AtomicInteger();
       <span class="hljs-keyword">for(<span class="hljs-keyword">int i=<span class="hljs-number">0;i<<span class="hljs-number">10;i++){
            Thread t=<span class="hljs-keyword">new Thread(<span class="hljs-keyword">new AtomicTest(atomicInteger));
            t.start();
            <span class="hljs-keyword">try {
               t.join(<span class="hljs-number">0);
           } <span class="hljs-keyword">catch (InterruptedException e) {
               e.printStackTrace();
           }

       }
       System.out.println(atomicInteger.get());
   }
}
<span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">AtomicTest <span class="hljs-keyword">implements <span class="hljs-title">Runnable{
   AtomicInteger atomicInteger;

   <span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-title">AtomicTest<span class="hljs-params">(AtomicInteger atomicInteger){
       <span class="hljs-keyword">this.atomicInteger=atomicInteger;
   }
   </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>

最终的输出结果为100,可见这个程序是线程安全的。如果把AtomicInteger换成变量i的话,那最终结果就不确定了。

打开AtomicInteger的源码可以看到:

<span class="hljs-keyword">private <span class="hljs-keyword">volatile <span class="hljs-keyword">int value;
</span></span></span>

volatile关键字用来保证内存的可见性(但不能保证线程安全性),线程读的时候直接去主内存读,写操作完成的时候立即把数据刷新到主内存当中。

从注释就可以看出:当线程写数据的时候,先对内存中要操作的数据保留一份旧值,真正写的时候,比较当前的值是否和旧值相同,如果相同,则进行写操作。如果不同,说明在此期间值已经被修改过,则重新尝试。
compareAndSet使用Unsafe调用native本地方法CAS(CompareAndSet)递增数值。

CAS利用CPU调用底层指令实现。
两种方式:总线加锁或者缓存加锁保证原子性。

Original: https://www.cnblogs.com/panxuejun/p/10200585.html
Author: THISISPAN
Title: (转)Java atomic原子类的使用方法和原理(一)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/536631/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 枚举

    枚举 自定义类实现枚举 1.不需要提供set方法,因为枚举对象值通常为只读2.对枚举对象/属性使用final + static共同修饰,实现底层优化3.枚举对象名通常使用全部大写,…

    Java 2023年6月5日
    078
  • nginx配置php-fpm虚拟主机站点

    ubuntu下安装nginx 很简单 sudo apt-get install nginx 然后安装php-fpm 我这本地php7.4所以这么写 然后好了以后改一下配置 /etc…

    Java 2023年5月30日
    056
  • MySQL索引凭什么能让查询效率提高这么多?

    我相信大家在数据库优化的时候都会说到索引,我也不例外,大家也基本上能对数据结构的优化回答个一二三,以及页缓存之类的都能扯上几句,但是有一次阿里P9的一个面试问我:你能从计算机层面开…

    Java 2023年6月9日
    0142
  • Spring配置 bean

    在 xml 文件中通过 bean 节点来配置 beanid:Bean 的名称。在 IOC 容器中必须是唯一的若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名…

    Java 2023年5月30日
    087
  • Java程序猿怎样高速理解Kubernetes

    我们希望微服务是可复制的。可替换的工作节点。这样能够轻松进行升级或降级,同一时候无需不论什么停机时间,并花费最少代价的管理。 我们能够说我们希望他们成为我们的小黄人(minions…

    Java 2023年5月29日
    062
  • spring boot2整合shiro安全框架实现前后端分离的JWT token登录验证

    https://blog.csdn.net/wozniakzhang/article/details/95855296?utm_medium=distribute.pc_relev…

    Java 2023年5月30日
    084
  • RabbitMQ—–死信队列

    1.什么是TTL? a. time to live 消息存活时间 b. 如果消息在存活时间内未被消费,则会被清除 c. RabbitMQ支持两种ttl设置 -单独消息进行配置ttl…

    Java 2023年5月30日
    079
  • 【spring-boot】使用Autowried还是Resouce

    在做项目时,发现项目中 加载类时,有的地方使用@Autowired,有的地方使用@Resource 在网上搜集了资料 共同点 @Resource和@Autowired都可以作为注入…

    Java 2023年5月29日
    066
  • test

    test posted @2022-05-03 22:29 且吃茶去 阅读(24 ) 评论() 编辑 //my Original: https://www.cnblogs.com/…

    Java 2023年6月8日
    075
  • mybatis 中 foreach collection的三种用法

    foreach元素的属性主要有 item,index,collection,open,separator,close。 在使用foreach的时候最关键的也是最容易出错的就是col…

    Java 2023年5月30日
    074
  • JDK成长记19:ReenranctLock(2)加锁入队的AQS底层原理

    上一节,你应该学到了ReentrantLock底层基于AQS的3个小组件 state、owner、queue。并且了解了下一个线程1进行加锁修改owner和state的过程。还记得…

    Java 2023年6月5日
    092
  • 代码生成器

    Mybatis Generator 使用xml配置文件形式自动生成 只生成实体类、mapper接口及mapper.xml。并且包含丰富的内容 首先添加mybatis依赖和相关插件 …

    Java 2023年6月13日
    080
  • Netty源码分析之ChannelPipeline(一)—ChannelPipeline的构造与初始化

    Netty中ChannelPipeline实际上类似与一条数据管道,负责传递Channel中读取的消息,它本质上是基于责任链模式的设计与实现,无论是IO事件的拦截器,还是用户自定义…

    Java 2023年6月9日
    062
  • Oracle备份与还原(实用版)

    Oracle备份与还原 EXP&#x548C;IMP&#x662F;&#x5BA2;&#x6237;&#x7AEF;&#x5DE5;…

    Java 2023年6月8日
    075
  • DBeaver配置Hive连接(转)

    https://blog.csdn.net/weixin_44374374/article/details/123957815 posted on2022-07-26 10:52 …

    Java 2023年6月8日
    076
  • 数组

    学习笔记——Java基础 数组 解决 : 将数据进行 存储 —-》引入∶数组 数组的作用 : 数组用来存储数据的,在程序设计中,为了处理方便,数组用来将相同类型的若干数…

    Java 2023年6月5日
    049
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球