先看一个例子,AtomicInteger 实现的线程安全的累加器

public class AtomicIntTest {
public static void main(String[] args) {
AddRunnable addRunnable = new AddRunnable();
Thread myThread1 = new Thread(addRunnable);
Thread myThread2 = new Thread(addRunnable);
myThread1.start();
myThread2.start();
try {
myThread1.join();
myThread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(addRunnable.count);
} } class AddRunnable implements Runnable {
AtomicInteger count = new AtomicInteger(); @Override
public void run() {
for (int i = 0; i < 100000; i++) {
count.incrementAndGet();
}
} }

AtomicInteger源码分析

下面通过AtomicInteger的源码来看一下是怎么在没有锁的情况下保证数据正确性。首先看一下incrementAndGet方法的实现

public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}

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

  注意::valueOffset叫做 偏移量 我们知道valueOffset指向的地址对应的值就是原始变量的值 执行逻辑就是 expect 和valueOffset 比较 相同 就替换成 update 不同继续循环

 

 总结:

1 虽然基于CAS的线程安全机制很好很高效,但要说的是,并非所有线程安全都可以用这样的方法来实现,这只适合一些粒度比较小,型如计数器这样的需求用起来才有效,否则也不会有锁的存在了。实际来发中,用锁的情况还是较多。

2 并发越高,失败的次数会越多,CAS如果长时间不成功,会极大的增加CPU的开销。(毕竟死循环嘛) 因此CAS不适合竞争十分频繁的场景。

3 CAS只能保证一个共享变量的原子操作。当对多个共享变量操作时,CAS就无法保证操作的原子性,这时就可以用锁,或者把多个共享变量合并成一个共享变量来操作。使用AtomicReference。

java多线程系列5 atomic简介的更多相关文章

  1. Java多线程系列——线程池简介

    什么是线程池? 为了避免系统频繁地创建和销毁线程,我们可以让创建的线程进行复用.用线程时从线程池中获取,用完以后不销毁线程,而是归还给线程池. JDK 对线程池的支持 为了更好的控制多线程,JDK 提 ...

  2. Java多线程系列九——Atomic类

    参考资料:https://fangjian0423.github.io/2016/03/16/java-AtomicInteger-analysis/http://www.cnblogs.com/54 ...

  3. java多线程系列 目录

    Java多线程系列1 线程创建以及状态切换    Java多线程系列2 线程常见方法介绍    Java多线程系列3 synchronized 关键词    Java多线程系列4 线程交互(wait和 ...

  4. Java多线程系列——从菜鸟到入门

    持续更新系列. 参考自Java多线程系列目录(共43篇).<Java并发编程实战>.<实战Java高并发程序设计>.<Java并发编程的艺术>. 基础 Java多线 ...

  5. java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析

    java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java ...

  6. Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例

    概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...

  7. Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例

    概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 ...

  8. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  9. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

随机推荐

  1. C#设计模式(2)——简单工厂模式(Factory )

    我们通过 Factory 创建对象不同的对象. 例如:如果创建一个汽车的接口,通过 工厂Factory 创建实现接口的对象,根据我们的选择来创建不同的对象. 创建汽车接口 /// <summar ...

  2. Bash常用快捷键及其作用

    在 Bash 中有非常多的快捷键,如果可以熟练地使用这些快捷键,可有效地提高我们的工作效率.只是快捷键相对较多,不太好记忆,这就要多加练习和使用.这些快捷键如表 1 所示. 表 1 Bash 常用快捷 ...

  3. halcon分离路径名称

    用haclon程序将目录名分离的算法. ParseFileName:='F:/D705/4-20/缺陷/81.bmp' parse_filename(ParseFileName, BaseName, ...

  4. 转载:c++深拷贝和浅拷贝

    文章来自:http://blog.csdn.net/u010700335/article/details/39830425 C++中类的拷贝有两种:深拷贝,浅拷贝:当出现类的等号赋值时,即会调用拷贝函 ...

  5. java 调用 python 的几种方法整理

    参考:   https://blog.csdn.net/secondlieutenant/article/details/79000265

  6. Rhythmk 一步一步学 JAVA(6): JSP 语法学习笔记

    1.修改JSP页面模版: 找到MyEclips安装目录,搜索“Jsp.vtl”,找到该文件修改编码,以及一些不需要用到的代码. 2.查找项目生成的Servlet文件路径: 查看当前项目父级目录搜索 . ...

  7. 14-background

    一.background-color:设置该元素的背景颜色 一共有三种:单词.rgb表示法.十六进制表示法 1.rgb:红色 绿色 蓝色 三原色 光学显示器,每个像素都是由三原色的发光原件组成的,靠明 ...

  8. eclipse 启动 闪退

    eclipse启动闪退 打开eclipse安装文件夹中的eclipse.ini文件. 把Xmx1024m修改为Xmx512m,可以解决闪退问题.

  9. ReactiveX 学习笔记(20)使用 RxJava + RxBinding 进行 GUI 编程

    课题 程序界面由3个文本编辑框和1个文本标签组成. 要求文本标签实时显示3个文本编辑框所输入的数字之和. 文本编辑框输入的不是合法数字时,将其值视为0. 3个文本编辑框的初值分别为1,2,3. 创建工 ...

  10. LeetCode OJ 102. Binary Tree Level Order Traversal

    题目 Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to rig ...