具体CAS操作实现(无锁算法)
具体CAS操作
上一篇讲述了CAS机制,这篇讲解CAS具体操作.
什么是悲观锁、乐观锁?在java语言里,总有一些名词看语义跟本不明白是啥玩意儿,也就总有部分面试官拿着这样的词来忽悠面试者,以此来找优越感,其实理解清楚了,这些词也就唬不住人了。
synchronized是悲观锁,这种线程一旦得到锁,其他需要锁的线程就挂起的情况就是悲观锁。
CAS操作的就是乐观锁,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。
那么问题来了,什么是CAS操作?
CAS是Compare-and-swap(比较与替换)的简写,是一种有名的无锁算法,在java中,我们主要分析Unsafe类,因为所有的CAS操作都是它来实现的,而在Unsafe类中这些方法也都是native方法
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
看到上面的解释是不是索然无味,查找了很多资料也没完全弄明白,通过几次验证后,终于明白,最终可以理解成一个无阻塞多线程争抢资源的模型。先上代码
package com.company.reentrantLock;
import java.util.concurrent.atomic.AtomicBoolean; public class AtomicBooleanTest implements Runnable{
public static AtomicBoolean exits = new AtomicBoolean(true);
public static void main(String[] args) {
AtomicBooleanTest abd = new AtomicBooleanTest();
Thread t1 = new Thread(abd);
Thread t2 = new Thread(abd);
t1.start();
t2.start();
}
@Override
public void run() {
System.out.println("begin run");
System.out.println("real " + exits.get());
if(exits.compareAndSet(true,false)){
System.out.println(Thread.currentThread().getName() + " " + exits.get() );
exits.set(true);
}else{
run();
}
}
}
输出结果:
begin run
real true
Thread-1 false
begin run
real true
Thread-0 false
这里无论怎么运行,Thread-1、Thread-0都会执行if=true条件,而且还不会产生线程脏读脏写,这是如何做到的了,这就用到了我们的compareAndSet(boolean expect,boolean update)方法,先上图简单讲解下程序原理,然后再分析compareAndSet作用。

这个图中重最要的是compareAndSet(true,false)方法要拆开成compare(true)方法和Set(false)方法理解,是compare(true)是等于true后,就马上设置共享内存为false,这个时候,其它线程无论怎么走都无法走到只有得到共享内存为true时的程序隔离方法区。 但是这种得不到状态为true时使用递归算法是很耗cpu资源的,所以一般情况下,都会有线程sleep。
总结
这篇文章并没有展开讲compareAndSet底层调用的是unsafe.compareAndSwapInt方法,因为这是native方法,很多人都会展开找源码,最后也只找到是调用CPU方法,没讲到具体用法,如果只用compareAndSet(true,false)举例则更加简单。 这种无阻塞式的多线程操作数据,在大并发情况下,是一笔非常可观的性能提升,所以,如果在大并发或多线程性能要求高的情况下有更加好的技术选型,可以参考这种底层实现。
结合JMM知识,线程间共享的变量,首先在主存中会保留一份,然后每个线程的工作内存也会保留一份副本.
我们对比发现,这里的预期值就是线程保留的副本,当该线程从主存中获取该变量值后,主存中该变量可能已经被其他线程刷新了,但是该线程工作内存中该变量却还是原来的值,这就是所谓的预期值.
当你要CAS刷新该值的时候,如果发现线程工作内存和主存中不一致,就会失败.如果一致,就可以更新成功
具体CAS操作实现(无锁算法)的更多相关文章
- 锁、CAS操作和无锁队列的实现
https://blog.csdn.net/yishizuofei/article/details/78353722 锁的机制 锁和人很像,有的人乐观,总会想到好的一方面,所以只要越努力,就会越幸运: ...
- 非阻塞同步算法与CAS(Compare and Swap)无锁算法
锁(lock)的代价 锁是用来做并发最简单的方式,当然其代价也是最高的.内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的上下文切换和调度延时,等待锁的线程会被挂起直至锁释放. ...
- CAS无锁算法与ConcurrentLinkedQueue
CAS:Compare and Swap 比较并交换 java.util.concurrent包完全建立在CAS之上的,没有CAS就没有并发包.并发包借助了CAS无锁算法实现了区别于synchroni ...
- 无锁算法CAS 概述
无锁算法CAS 概述 JDK5.0以后的版本都引入了高级并发特性,大多数的特性在java.util.concurrent包中,是专门用于多线并发编程的,充分利用了现代多处理器和多核心系统的功能以编写大 ...
- 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法
转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...
- java并发:AtomicInteger 以及CAS无锁算法【转载】
1 AtomicInteger解析 众所周知,在多线程并发的情况下,对于成员变量,可能是线程不安全的: 一个很简单的例子,假设我存在两个线程,让一个整数自增1000次,那么最终的值应该是1000:但是 ...
- CAS(Compare and Swap)无锁算法-学习笔记
非阻塞同步算法与CAS(Compare and Swap)无锁算法 这篇问题对java的CAS讲的非常透彻! 锁的代价 1. 内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的 ...
- CAS原子操作实现无锁及性能分析
CAS原子操作实现无锁及性能分析 Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn.net/chen19870707 ...
- 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
随机推荐
- Django的一些隐性经验
隐性经验 前后信息的沟通 url中的参数 get获取 这个参数可以写在URL当中(可以写多个,写在这里的get函数需要有相应的参数去获取).,也可以在模版中添加(通过?若是直接写则表示在当前的URL中 ...
- 7.ASP.NET MVC 5.0中的Routing【路由】
大家好,这一篇向大家介绍ASP.NET MVC路由机制.[PS:上一篇-->6. ASP.NET MVC 5.0中的HTML Helpers[HTML帮助类] ] 路由是一个模式匹配系统,它确保 ...
- Zhu-Takaoka Two-dimensional Pattern Matching
Two dimensional pattern matching. Details may be added later.... Corresponding more work can be foun ...
- 770. Basic Calculator IV
Given an expression such as expression = "e + 8 - a + 5" and an evaluation map such as {&q ...
- redis 分布式读写锁
http://zhangtielei.com/posts/blog-redlock-reasoning.html 链接里这篇 blog 讨论了 redis 分布式锁的实现以及安全性 我要参考 基于单R ...
- Java中的Lock接口
Synchronized & Lock synchronized 是Java语言中的关键字,由monitorenter,monitorexit两个指令实现.JVM会将monitorenter指 ...
- css3 动画与display:none冲突的解决方案
概述 css不能在display:none和display:block之间进行动画,并且也不能在height:0和height:auto之间进行动画.这里我研究了一下在display:none和dis ...
- SpringCloud-Eurake坑
首先遇到的问题 Eurake单台部署,很容易出现自我保护,发现web管理页面一大串红字警告 这个问题通过关闭自我保护机制可以简单解决..一般集群部署不会出现 eureka: server: renew ...
- css高级选择器&盒模型
css高级选择器&盒模型 1.组合选择器 群组选择器 /* 每个选择器为可以为三种基础选择器的任意一个,用逗号隔开,控制多个*/ div,.div,#div{ color:red } 后代(子 ...
- Eclipse上搭建Spring的开发环境
一.安装Spring Tool Suite插件 如图: 点击Finish之后等待安装,安装完之后弹窗点击yes重启Eclipse,重启后显示如下界面: 二.搭建Spring开发环境 1.导入jar包到 ...