先看一个例子,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. 关于APS在企业生产计划上的应用

    本人本身是一个码农,已经服务了共和国各项事业(好像是说得有点漂,没办法段子看多了)大约一半工作时候了(按60岁退休的话),从一线的小码农,到现在成了老农,出产了不少或优或劣的各种码,几乎啥都做过.近几 ...

  2. go语言学习--处理map的无序输出

    最近工作中遇到了这样的一个场景,需要处理一个无限极分类的问题,对于数据结构的定义首先想到了,map,map[int]map[int]struct.通过两层map的定义归类parent_id和id的关系 ...

  3. docker上部署nginx容器80端口自动转443端口

    拉去nginx镜像 # docker pull nginx 运行nginx容器config用于拷贝nginx配置文件 # docker run --name nginxconfig -d docker ...

  4. centos7 安装percona-toolkit工具包的安装和使用

    一.检查和安装与Perl相关的模块 PT工具是使用Perl语言编写和执行的,所以需要系统中有Perl环境. 依赖包检查命令为: rpm -qa perl-DBI perl-DBD-MySQL perl ...

  5. WordPress版微信小程序2.1.5版发布

    WordPress版微信小程序功能已经基本完善,利用这套程序,搭配WordPress提供的rest api,WordPress网站的站长可以快速搭建属于自己的网站微信小程序 . WordPress版微 ...

  6. Vue Checkbox全选和选中的方法

    <div class="search-content"> <Checkbox :value="checkAll" @click.prevent ...

  7. BZOJ 3097: Hash Killer I

    3097: Hash Killer I Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special Judge[Submit][Status][Discus ...

  8. [解决]CXF wsdl2java 生成代码存在的一些问题

    1.环境 CXF版本:3.2.4 JDK版本:1.8.0_112 2.问题 2.1.问题种类1 属性 "Value" 已定义.请使用 <jaxb:property> 解 ...

  9. leetcode1027

    最直接的思路是三层循环,但是会超时,代码如下: public class Solution { public int LongestArithSeqLength2(int[] A) { ; var l ...

  10. Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。

    借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...