(转)Java atomic原子类的使用方法和原理(一)
在讲atomic原子类之前先看一个小例子:
public class UseAtomic {
   public static void main(String[] args) {
       AtomicInteger atomicInteger=new AtomicInteger();
       for(int i=0;i<10;i++){
            Thread t=new Thread(new AtomicTest(atomicInteger));
            t.start();
            try {
               t.join(0);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
       System.out.println(atomicInteger.get());
   }
}
class AtomicTest implements Runnable{
   AtomicInteger atomicInteger;
   public AtomicTest(AtomicInteger atomicInteger){
       this.atomicInteger=atomicInteger;
   }
   @Override
   public void run() {
       atomicInteger.addAndGet(1);
       atomicInteger.addAndGet(2);
       atomicInteger.addAndGet(3);
       atomicInteger.addAndGet(4);
   }
}
最终的输出结果为100,可见这个程序是线程安全的。如果把AtomicInteger换成变量i的话,那最终结果就不确定了。
打开AtomicInteger的源码可以看到:
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private volatile int value;
volatile关键字用来保证内存的可见性(但不能保证线程安全性),线程读的时候直接去主内存读,写操作完成的时候立即把数据刷新到主内存当中。
CAS简要
/**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
从注释就可以看出:当线程写数据的时候,先对内存中要操作的数据保留一份旧值,真正写的时候,比较当前的值是否和旧值相同,如果相同,则进行写操作。如果不同,说明在此期间值已经被修改过,则重新尝试。
compareAndSet使用Unsafe调用native本地方法CAS(CompareAndSet)递增数值。
CAS利用CPU调用底层指令实现。
两种方式:总线加锁或者缓存加锁保证原子性。
作者:zxin1
链接:https://www.jianshu.com/p/a2f3c46d4783
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
(转)Java atomic原子类的使用方法和原理(一)的更多相关文章
- Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。
		精彩理解: https://www.jianshu.com/p/21be831e851e ; https://blog.csdn.net/heyutao007/article/details/19 ... 
- Java线程--Atomic原子类使用
		原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871241.html Java线程--Atomic原子类使用 package concurr ... 
- JUC 中的 Atomic 原子类总结
		1 Atomic 原子类介绍 Atomic 翻译成中文是原子的意思.在化学上,我们知道原子是构成一般物质的最小单位,在化学反应中是不可分割的.在我们这里 Atomic 是指一个操作是不可中断的.即使是 ... 
- Atomic原子类
		Atomic原子类 Atomic原子类位于并发包java.util.concurrent下的java.util.concurrent.Atomic中. 1. 原子更新基本类型类 使用原子方式更新基本数 ... 
- java 线程  原子类相关操作演示样例 thinking in java4  文件夹21.3.4
		java 线程 原子类相关操作演示样例 package org.rui.thread.volatiles; import java.util.Timer; import java.util.Time ... 
- Juc中Atomic原子类总结
		1 Atomic原子类介绍 2 基本类型原子类 3 数组类型原子类 4 引用类型原子类 5 对象的属性修改类型原子类 
- 并发编程学习笔记(4)----jdk5中提供的原子类及Lock使用及原理
		(1)jdk中原子类的使用: jdk5中提供了很多原子类,它会使变量的操作变成原子性的. 原子性:原子性指的是一个操作是不可中断的,即使是在多个线程一起操作的情况下,一个操作一旦开始,就不会被其他线程 ... 
- [Java多线程]-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
		前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ... 
- Java并发—原子类,java.util.concurrent.atomic包(转载)
		原子类 Java从JDK 1.5开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中 的原子操作类提供了一种用法简单.性能高效.线程安全地更新一个变量 ... 
随机推荐
- IDEA运行TestNG报错rg.testng.TestNGException: org.xml.sax.SAXParseException;
			从eclipse复制的依赖注解,一运行测试脚本发现报错如下: "F:\Program Files\Java\jdk1.7.0_17\bin\java" -ea -Didea.lau ... 
- 5种PHP创建数组的方式
			在PHP以及其他程序语言程序设计中,经常会用到数组的创建,在前端开发中,js的数组创建可以由[]和new Array()直接创建和赋值.然而PHP创建数组的方法有哪些呢?在查阅资料并且网上收集整理总结 ... 
- ie6 表格td中无内容时不显示边框的解决办法
			1.在单元格中加入一个空格.这样: <td> </td> 2.直接在table里这样写:<table border="0" cellspacing=& ... 
- Linux mount 修改文件系统的读写属性
			有时候要在某个文件夹下添加和删除文件时,显示 "read only filesystem",说明该文件系统是只读的不能修改.使用 mount –o remount,rw / 命令可 ... 
- Slick.js+Animate.css 结合让网页炫动起来
			一个代码示例: html部分 <link rel='stylesheet prefetch' href='//cdnjs.cloudflare.com/ajax/libs/animate.css ... 
- PHP 抽象类
			* 抽象类 * 1.使用关键字: abstract * 2.类中只要有一个方法声明为abstract抽象方法,那么这个类就必须声明为抽象类 * 3.抽象方法只允许有方法声明与参数列表,不允许有方法体; ... 
- 性能测试九:jmeter进阶之beanshell的使用+断言
			一.使用 BeanShell使用方式一 BeanShell面板上写脚本 // 从vars中获取用户定义的参数,并转换为int类型 int p_skuId = Integer.parseInt(vars ... 
- 性能测试三:jmeter进阶之图形插件
			一.图形化插件的使用 使用Jmeter插件可以更直观的查看tps和响应时间 插件官网: http://jmeter-plugins.org/downloads/all 第一种方法,找到需要的插件下载j ... 
- python接口自动化测试十六:unittest完成用例
			import unittestimport requests def add(a, b): print('前置条件!!!!!:如登录') return a + b class TestAAA(unit ... 
- POJ 1995 Raising Modulo Numbers (快速幂)
			题意: 思路: 对于每个幂次方,将幂指数的二进制形式表示,从右到左移位,每次底数自乘,循环内每步取模. #include <cstdio> typedef long long LL; LL ... 
