- 浏览: 183390 次
- 性别:
- 来自: 杭州
博客专栏
-
Java技术分享
浏览量:0
文章分类
最新评论
-
masuweng:
学习了,学习了
mybatis是如何防止SQL注入的 -
somefuture:
终于知道了#$的区别
mybatis是如何防止SQL注入的 -
masuweng:
...
tomct处理请求的流程 -
zhp8341:
masuweng 写道寻求cas的更多例子, http://w ...
JUC之CAS -
臻是二哥:
java.util.concurrent包中到处都使用了CAS ...
JUC之CAS
JUC是java.util.concurrent包的简称,该包提供了并发编程的解决方案(当然,JAVA并发编程的解决方案还有synchronized)。从概括的层面来说,JUC包有两大核心:CAS和AQS。其中CAS是java.util.concurrent.atomic包的基础,AQS是java.util.concurrent.locks包以及一些常用类比如Semophore等类的基础。我们先来说说CAS。
CAS的全称为Compare-And-Swap,它是一条CPU并发原语。它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。CAS并发原语体现在JAVA语言中就是sun.misc.Unsafe类中的各个方法。调用UnSafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能。那么为什么CAS会出现呢?它的作用是怎样的?
实现并发的传统方式是加锁,JAVA中的锁有synchronized和Lock。Lock是基于AQS和CAS实现的,在此先不叙述。对于synchronized锁,JVM在执行它的时候会依赖操作系统的临界区机制。这样的话,每次执行到synchronized锁,都会经历用户态和内核态之间的切换。这个过程的消耗是很大的。而且,大多数时候synchronized锁住的操作是很细粒度的。为了细粒度的操作去经历用户态和内核态之间的切换是低效的做法。
说到这,我想到了线程池。大家知道,当线程创建和销毁的时间大于任务执行的时间时,就需要考虑使用线程池了。但如果和任务执行时间相比,线程创建和销毁的时间很少,那么线程池也可不用。
在synchronized中就是这个问题,当需要同步的操作粒度很细时,使用synchronized是不高效的,这时就有CAS存在的意义了。比如对于i++这种并发计数功能,使用synchronized就大材小用了,而使用CAS来实现就会更加的轻量级,性能更好。因此可以看到java.util.concurrent.atomic包中有类似AtomicInteger这种类。我们来看下AtomicInteger类的核心源码:
在上面的代码中Unsafe类负责执行CAS并发原语,由JVM转化为汇编。在代码中使用CAS自旋volatile变量的形式实现非阻塞并发。这种方式是CAS的主要使用方式。
CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置。无论如何,告诉我原值。
Java.util.concurrent.atomic包为开发者提供了比synchronized更加细粒度的并发代码控制方式。实际上也是最细粒度的并发代码控制方式。
CAS是乐观锁,是一种冲突重试的机制,在并发竞争不是很激烈的情况下(也是大多数情况),他的性能要好于基于锁的并发性能。因为并发竞争激烈的话,冲突重试的过程很多。
下面是基于AtomicReference实现的并发的非阻塞栈:
CAS的典型步骤如下:
在上面代码的mark1行,首先获取V的值为A,然后在mark2行会重新判断V的值是否还是A。现实中有这样的情况:在mark1行之后mark2行之前,V的值可能从A变成B又变成A。这个时候,现有的代码仍然认为V的值没有改变,而有些情况下,我们需要识别V的这种改变。这就是ABA问题。
解决ABA问题的一种思路就是在CAS操作的时候更新两个值,包括引用和该值的版本号,JUC中提供了这个类AtomicStampedReferance以及AtomicMarkedReference。这两个类支持在两个变量上执行CAS操作,用于解决ABA问题。
CAS的全称为Compare-And-Swap,它是一条CPU并发原语。它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。CAS并发原语体现在JAVA语言中就是sun.misc.Unsafe类中的各个方法。调用UnSafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能。那么为什么CAS会出现呢?它的作用是怎样的?
实现并发的传统方式是加锁,JAVA中的锁有synchronized和Lock。Lock是基于AQS和CAS实现的,在此先不叙述。对于synchronized锁,JVM在执行它的时候会依赖操作系统的临界区机制。这样的话,每次执行到synchronized锁,都会经历用户态和内核态之间的切换。这个过程的消耗是很大的。而且,大多数时候synchronized锁住的操作是很细粒度的。为了细粒度的操作去经历用户态和内核态之间的切换是低效的做法。
说到这,我想到了线程池。大家知道,当线程创建和销毁的时间大于任务执行的时间时,就需要考虑使用线程池了。但如果和任务执行时间相比,线程创建和销毁的时间很少,那么线程池也可不用。
在synchronized中就是这个问题,当需要同步的操作粒度很细时,使用synchronized是不高效的,这时就有CAS存在的意义了。比如对于i++这种并发计数功能,使用synchronized就大材小用了,而使用CAS来实现就会更加的轻量级,性能更好。因此可以看到java.util.concurrent.atomic包中有类似AtomicInteger这种类。我们来看下AtomicInteger类的核心源码:
public class AtomicInteger extends Number implements java.io.Serializable { private static final long serialVersionUID = 6214790243416807050L; // setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile int value; public AtomicInteger(int initialValue) { value = initialValue; } public AtomicInteger() { } public final int get() { return value; } public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } public final int incrementAndGet() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return next; } } }
在上面的代码中Unsafe类负责执行CAS并发原语,由JVM转化为汇编。在代码中使用CAS自旋volatile变量的形式实现非阻塞并发。这种方式是CAS的主要使用方式。
CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置。无论如何,告诉我原值。
Java.util.concurrent.atomic包为开发者提供了比synchronized更加细粒度的并发代码控制方式。实际上也是最细粒度的并发代码控制方式。
CAS是乐观锁,是一种冲突重试的机制,在并发竞争不是很激烈的情况下(也是大多数情况),他的性能要好于基于锁的并发性能。因为并发竞争激烈的话,冲突重试的过程很多。
下面是基于AtomicReference实现的并发的非阻塞栈:
import java.util.concurrent.atomic.AtomicReference; public class ConcurrentStack <E>{ private AtomicReference<Node<E>> top=new AtomicReference<Node<E>>(); public void push(E value){ Node<E> newTop=new Node<E>(value); Node<E> oldTop=null; do{ oldTop=top.get(); newTop.next=oldTop; }while(!top.compareAndSet(oldTop,newTop)); } public E pop(){ Node<E> node=null; Node<E> newTop=null; do{ node=top.get(); if(node==null) return null; newTop=node.next; node.next=null; }while(!top.compareAndSet(node, newTop)); return node.value; } private class Node<E>{ public Node<E> next; public final E value; public Node(E value){ this.value=value; } } }
CAS的典型步骤如下:
while(true){ int A=V.get();//mark1 if(A==V.compareAndSwap(A,newA))//mark2 return A; }
在上面代码的mark1行,首先获取V的值为A,然后在mark2行会重新判断V的值是否还是A。现实中有这样的情况:在mark1行之后mark2行之前,V的值可能从A变成B又变成A。这个时候,现有的代码仍然认为V的值没有改变,而有些情况下,我们需要识别V的这种改变。这就是ABA问题。
解决ABA问题的一种思路就是在CAS操作的时候更新两个值,包括引用和该值的版本号,JUC中提供了这个类AtomicStampedReferance以及AtomicMarkedReference。这两个类支持在两个变量上执行CAS操作,用于解决ABA问题。
评论
3 楼
zhp8341
2016-07-27
2 楼
臻是二哥
2016-07-27
java.util.concurrent包中到处都使用了CAS和AQS,可以看源码
1 楼
masuweng
2016-07-27
寻求cas的更多例子,
发表评论
-
精心准备的讲解Java多线程的知乎Live
2018-09-02 21:39 704花了一个月的时间,结合自己的理解,制作了一个以图片的方式讲解J ... -
在知乎推出Java求职类专栏文章
2018-08-27 12:06 790从昨天起,笔者开始在知乎推出Java求职类专栏文章,主要涉及一 ... -
JUC之AQS
2016-07-27 15:49 1205AQS是同步框架,它进行 ... -
JAVA并发-线程状态和线程组
2016-07-18 14:14 1267在Java中,线程有6种基本状态,理解这6种基本状态之间的关系 ... -
JAVA并发-条件队列
2016-07-02 09:57 1115在JVM系列博客http://yizhen ... -
JAVA并发-中断处理和任务取消
2016-06-27 22:42 1196中断处理 在java程序中 ... -
JAVA并发-显式锁(二)
2016-06-06 09:25 1024在上一篇博客《JAVA并发-显式锁(一)》中介绍了Lock和R ... -
JAVA并发-显式锁(一)
2016-06-05 20:40 891JAVA语言除了提供内置锁synchronized,还在JDK ... -
JAVA并发-减少锁的竞争
2016-06-04 16:01 1846降低锁的竞争可以提高 ... -
JAVA并发-3种典型的死锁
2016-06-03 19:54 1621在JAVA并发编程中,我们 ... -
JAVA并发-3种典型的死锁
2016-06-03 10:02 10在JAVA并发编程中,我们 ... -
JAVA并发-ThreadPoolExecutor线程池的使用
2016-05-30 16:19 2356在博客JAVA并发-Executor任务执行框架中曾说过,Ex ... -
JAVA并发-Executor任务执行框架
2016-05-27 19:10 432首先介绍两个重要的接 ... -
JAVA并发-DCL与JMM
2016-04-26 19:21 1568首先必须声明,在volatil ... -
JAVA并发- 典型连接池的实现
2016-04-22 10:44 1134package com.xyz.connpool; pu ... -
JAVA并发-构建可靠的结果缓存
2016-04-10 16:58 55在学习了前面关于多线程的博客之后,下面来介绍一个构建可靠结果缓 ... -
JAVA并发-并发编程常用类
2016-04-08 11:07 991在讲同步工具类之前,笔者想先介绍一下Runnable,Call ... -
JAVA并发-同步容器和并发容器
2016-04-07 19:02 698常见的同步容器类包括V ... -
JAVA并发-开发线程安全类
2016-04-01 10:23 840我们知道,面向对象的 ... -
JAVA并发-为现有的线程安全类添加原子方法
2016-03-30 20:46 1390JAVA中有许多线程安全的基础模块类,一般情况下,这些基础模块 ...
相关推荐
尚硅谷_JUC线程高级_原子变量与 CAS 算法 ·3. 尚硅谷_JUC线程高级_模拟 CAS 算法 ·4. 尚硅谷_JUC线程高级_同步容器类ConcurrentHashMap ·5. 尚硅谷_JUC线程高级_CountDownLatch 闭锁 ·6. 实现 Callable 接口 ·...
Java 多线程与并发(8_26)-JUC原子类_ CAS, Unsafe和原子类详解
JUC包含线程,线程池,CAS,volatile等底层原理,以及相关问题的解决方式以及相关工具类的使用,包含但不限于:synchronize的底层原理,线程的执行流程,lock锁底层原理等,线程不安全的集合以及底层等.
JUC最详细思维导图,一次了解读写锁,可重入锁,Cas原理,volatile 关键字原理
Java多线程(Synchronized+Volatile+JUC 并发工具原理+线程状态+CAS+线程池)
JAVA1.5开始引入了CAS,JUC下很多工具类都是基于CAS。 CAS的实现方式 CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。当多个线程同时...
包括JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。上半场,从多线程并发入手,分层递进讲解,逐步让大家掌握volatile、原子类和原子引用、CAS、ABA、Java锁机制、阻塞队列、...
本期内容包括JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。上半场,从多线程并发入手,分层递进讲解,逐步让大家掌握volatile、原子类和原子引用、CAS、ABA、Java锁机制、...
JUC、JMM核心知识点笔记 尚硅谷周阳老师课程——笔记。 / / JUC知识点 JMM volatile关键字 可见性 原子性 有序性 哪些地方用到过volatile? 单例模式的安全问题 CAS CAS底层原理 CAS缺点 ABA问题 AtomicReference ...
java 中的乐观锁基本都是通过 CAS 操作实现的,CAS 是一种更新的原子操作,比较当前值跟传入 值是否一样,一样则更新,否则失败2,悲观锁 悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的...
java.util.concurrent ,包 对应JUC并发编程 笔记和JUC-API 还有 Java原子类 CAS
一、理论基础 1.1为什么需要多线程 1.2不安全示例 1.3并发问题的根源 1.4JMM 1.5线程安全的分类 1.6线程安全的方法 二、线程基础 ...十、原子类-CAS, Unsafe和原子类详解 十一、JUC锁: LockSupport详解
JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。上半场,从多线程并发入手,分层递进讲解,逐步让大家掌握volatile、原子类和原子引用、CAS、ABA、Java锁机制、阻塞队列、...
本期内容包括JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。上半场,从多线程并发入手,分层递进讲解,逐步让大家掌握volatile、原子类和原子引用、CAS、ABA、Java锁机制、...
资源概要:1,多线程;2,synchronized;3,volatile;4,多线程在JVM中的实现...原子类Atomic-CAS及其实现原理 锁Lock-AQS核心原理剖析 并发工具类、并发容器、阻塞队列 线程池原理剖析 线程池案例-Web容器-压力测试
框架开发学习 此仓库给出了在框架开发中经常使用的不同Java概念和编程技术的示例。 例如,当我们想从头开始创建RPC... Java JUC 完毕 Java CAS java-cas 完毕 Java SPI java-spi JDBC 完毕 Java零拷贝 Java零复制
12、常用JUC类:CountDownloadLatch,CylicBarrier、ReetrantLock等测试案例 13、自定义封装的并发工具类:ConcurrentAction 14、自定义限流注解和其他工具注解 15、AQS队列学习总结和测试 16、CAS学习总结和测试 17...
JUC、死锁、CAS、线程池 第四篇:JVM 那点破事!内存结构、垃圾收集、OOM、双亲委派 第五篇:项目亮点!DDD、系统架构、分库分表、高性能、吞吐量 第六篇:面试那点破事!面试技巧、职业规划、谈薪资 第七篇:Redis ...
上半场,从多线程并发入手,分层递进讲解,逐步让大家掌握volatile、原子类和原子引用、CAS、ABA、Java锁机制、阻塞队列、线程池等重点;下半场,逐步过渡到JVM和GC的知识,深度讲解多种常见OOM异常和JVM参数调优,...