java多线程-cas及atomic
大纲:
- cas
- atomic
一、cas
cas:compareAndSwap,一种乐观锁。
cas思想:cas需要三个值,v是内存值,e是期望值,n是要修改的值。当内存中的值v等于预期值e(说明内存中的值没有被其他线程修改)、才可以修改v为n。
cas伪代码
boolean cas(int v,int e,int n){
if(v==e){
v=n;
return true;
}else {
return false;
}
}
cas是unsafe类中的native方法,是原子操作,保证线程安全。
二、atomic
在java.util.concurrent.atomic包中,提供了许多拥有原子操作的类,供并发编程使用。这个包中的类大都使用了cas操作来保证操作的原子性。
以AtomicInteger为例,看下如何使用cas实现原子操作,这里为java1.8以下的源码:
public class AtomicInteger extends Number implements java.io.Serializable { private volatile int value; //volatile保证可见性,一个线程更新后,其他线程立即可见 public final int get() {
return value;
} public AtomicInteger(int initialValue) {
value = initialValue;
} public final int getAndIncrement() {
for (;;) {
int current = get();//预期值e
int next = current + 1;//要修改的值n
if (compareAndSet(current, next))
return current;
}
//这个相当于线程安全的a++操作,其思想就是不断进行cas操作,直至成功
} public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
//给bootStrap类加载器用的unsafe中全部是native方法。
// valueOffset为变量在内存中偏移地址,用来找内存中的值v
} ......
}
ABA问题:一个线程在cas操作时,期望值是A,另一个线程修改了期望值为B,就会导致cas操作失败。但是如果这时候又有一个线程再次修改期望值为A,cas操作将成功。
如何解决:atomic包下AtomicStampedReference
public class AtomicStampedReference<V> { private static class Pair<T> {
final T reference;
final int stamp;
private Pair(T reference, int stamp) {
this.reference = reference;
this.stamp = stamp;
}
static <T> Pair<T> of(T reference, int stamp) {
return new Pair<T>(reference, stamp);
}
} private volatile Pair<V> pair; public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
//AtomicStampedReference内部有一个静态内部类pair,pair不仅封装了数据还封装了一个stamp用于区分每次修改
} public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp))); //cas比较pair对象(不仅比较内存值如期望值,同时比较期望stamp与内存stamp)
} private boolean casPair(Pair<V> cmp, Pair<V> val) {
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
} ...
}
java多线程-cas及atomic的更多相关文章
- Java 多线程 volitile 和 atomic
Java 多线程 volitile 和 atomic volitile关键字 public class MTester { public static class TestKey{ int x = 0 ...
- Java多线程--CAS
在Java多线程并发的情况下同时对一个变量进行操作会出现线程安全的问题,假如我们现在使用20个线程对一个变量不停累加1,代码如下: 1 public class ThreadDemo implemen ...
- Java多线程系列九——Atomic类
参考资料:https://fangjian0423.github.io/2016/03/16/java-AtomicInteger-analysis/http://www.cnblogs.com/54 ...
- java多线程系列5 atomic简介
先看一个例子,AtomicInteger 实现的线程安全的累加器 public class AtomicIntTest { public static void main(String[] args) ...
- java多线程系列 目录
Java多线程系列1 线程创建以及状态切换 Java多线程系列2 线程常见方法介绍 Java多线程系列3 synchronized 关键词 Java多线程系列4 线程交互(wait和 ...
- java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析
java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java ...
- Java多线程系列——原子类的实现(CAS算法)
1.什么是CAS? CAS:Compare and Swap,即比较再交换. jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronou ...
- java 多线程12 : 无锁 实现CAS原子性操作----原子类
由于java 多线程11:volatile关键字该文讲道可以使用不带锁的情况也就是无锁使变量变成可见,这里就理解下如何在无锁的情况对线程变量进行CAS原子性及可见性操作 我们知道,在并发的环境下,要实 ...
- Java并发(十二):CAS Unsafe Atomic
一.Unsafe Java无法直接访问底层操作系统,而是通过本地(native)方法来访问.不过尽管如此,JVM还是开了一个后门,JDK中有一个类Unsafe,它提供了硬件级别的原子操作. 这个类尽管 ...
随机推荐
- 3.3.7 跳表 SkipList
一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下,ConcurrentHashMap 存取速度是ConcurrentSki ...
- libxml2
http://www.xmlsoft.org/downloads.html 建议直接用openscenegraph下载的3rdparty:http://www.openscenegraph.org ...
- 数据库工具链接阿里云MySQL数据库
数据库工具:Toad for MySQL ssh工具:XShell 5 跳板机配置: 配置通道: 源主机:数据库工具链接的地址: 侦听接口:数据库工具侦听接口: 目标主机:数据库阿里云地址: 目标端口 ...
- 正则表达式(javascript)
在开发过程中要要把一个css中的平移的x,y提取出来 ,正好把正则表达式学习了一下 'fsdfsdfsdf300pxfdsfd200pxfsdfsdf100px' 找出里面 px前面的数字: 经查资 ...
- Partition--分区Demo
--============================================================= --创建分区函数 --创建500分区,分区键按照1000依次递增 CRE ...
- Spring MVC 基本配制
WEB.XML 文件中的配制: <?xml version="1.0" encoding="UTF-8"?> <web-app id=&quo ...
- leetcode 有效的数独
判断一个 9x9 的数独是否有效.只需要根据以下规则,验证已经填入的数字是否有效即可. 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以粗实线分隔的 ...
- scrapy-redis3
原文链接:scrapy-redis使用以及剖析
- 转载:spring boot学习
Spring Boot学习 Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置. 简单来说,它提 ...
- Android学习之 adb被占用解决办法
1.adb被占用解决办法 方法一:(1)查看5037端口哪个进程在用 netstat -a -o 5037 (2)查看上面进程是哪个执行文件在占用 tasklist ...