public class Snippet {
//修改的是AtomicStampedReference对象里面的值了。
public static void main(String[] args) {
//现在AtomicStampedReference里面的pair是{aaa,1},
AtomicStampedReference<String> reference = new AtomicStampedReference<String>("aaa",);
System.out.println(reference.compareAndSet("aaa","bbb",reference.getStamp(),reference.getStamp()+));
//现在AtomicStampedReference里面的pair是{bbb,2},
System.out.println("reference.getReference() = " + reference.getReference()); //只是修改版本,不修改值,现在AtomicStampedReference里面的pair是{bbb,3},
boolean b = reference.attemptStamp("bbb", reference.getStamp() + );
System.out.println("b: "+b);
System.out.println("reference.getStamp() = "+reference.getStamp()); boolean c = reference.weakCompareAndSet("bbb","ccc",, reference.getStamp()+);
System.out.println("reference.getReference() = "+reference.getReference());
System.out.println("c = " + c);//现在AtomicStampedReference里面的pair是{bbb,3},
}
}
public class AtomicStampedReference<V> {

    private static class Pair<T> {//将值和版本号封装为一个Pair,比较就是比较这个Pair。
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;//多个线程同时修改这个pair要可见。比如:一直自加到100 public AtomicStampedReference(V initialRef, int initialStamp) {//构造AtomicStampedReference时候把要多线程修改的
//值封装成pair
pair = Pair.of(initialRef, initialStamp);
} public V getReference() {//获取准备通过AtomicStampedReference来改变的值。
return pair.reference;
} public int getStamp() {//获取准备通过AtomicStampedReference来改变的值的版本号。
return pair.stamp;
} public V get(int[] stampHolder) {
Pair<V> pair = this.pair;
stampHolder[] = pair.stamp;
return pair.reference;
} public boolean weakCompareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
return compareAndSet(expectedReference, newReference,
expectedStamp, newStamp);
}
//旧值修改为新值。有3个:现在值2个,期望现在值2个,新值2个。
//期望值和现在值2个相等,前提下,新值和现在值2个都相等不改变,否则该变。
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
//现在值和期望现在值里面2个一样直接返回false不需要更新。
expectedReference == current.reference &&
expectedStamp == current.stamp &&
//现在值和期望现在值里面2个一样需要更新
//新值和现在值2个都一样返回false不需要更新
((newReference == current.reference &&
newStamp == current.stamp) ||
//现在值和期望现在值里面2个一样,并且新值和现在值有一个不一样,需要更新。
casPair(current, Pair.of(newReference, newStamp)));//改变旧的pair为新的pair,新的pair要重新构造一个新的。
} public void set(V newReference, int newStamp) {
Pair<V> current = pair;
if (newReference != current.reference || newStamp != current.stamp)
this.pair = Pair.of(newReference, newStamp);
} public boolean attemptStamp(V expectedReference, int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
(newStamp == current.stamp ||
casPair(current, Pair.of(expectedReference, newStamp)));
} // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
private static final long pairOffset =
objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class); private boolean casPair(Pair<V> cmp, Pair<V> val) {
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);//改变里面的pair从cmp到val
} static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
String field, Class<?> klazz) {
try {
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
} catch (NoSuchFieldException e) {
// Convert Exception to corresponding Error
NoSuchFieldError error = new NoSuchFieldError(field);
error.initCause(e);
throw error;
}
}
}

AtomicStampedReference源码分析的更多相关文章

  1. 死磕 java并发包之AtomicStampedReference源码分析(ABA问题详解)

    问题 (1)什么是ABA? (2)ABA的危害? (3)ABA的解决方法? (4)AtomicStampedReference是什么? (5)AtomicStampedReference是怎么解决AB ...

  2. AtomicStampedReference 源码分析

    AtomicStampedReference AtomicStampedReference 能解决什么问题?什么时候使用 AtomicStampedReference? 1)AtomicStamped ...

  3. AtomicInteger源码分析——基于CAS的乐观锁实现

    AtomicInteger源码分析——基于CAS的乐观锁实现 1. 悲观锁与乐观锁 我们都知道,cpu是时分复用的,也就是把cpu的时间片,分配给不同的thread/process轮流执行,时间片与时 ...

  4. Java高并发之无锁与Atomic源码分析

    目录 CAS原理 AtomicInteger Unsafe AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntege ...

  5. 并发-AtomicInteger源码分析—基于CAS的乐观锁实现

    AtomicInteger源码分析—基于CAS的乐观锁实现 参考: http://www.importnew.com/22078.html https://www.cnblogs.com/mantu/ ...

  6. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  7. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  8. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  9. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

随机推荐

  1. jQuery (02) 重点知识点总结

    jQuery 如果用户未登录,当加入购物车,会将商品相关信息存入 cookie 或者 session,这两个都是可以标识用户信息的东西 是一个 JavaScript 库,封装了常用的开发功能,和一些需 ...

  2. opencv 常用头文件介绍

    1.OpenCV包含的模块 cv – 核心函数库 cvaux – 辅助函数库 cxcore – 数据结构与线性代数库 highgui – GUI函数库 ml – 机器学习函数库 2.常用头文件: #i ...

  3. 在 CentOS7 安装 ELK

    ELK是一个成熟的日志系统,主要功能有收集.分析.检索,详细见 elastic官网. 本文主要介绍如何在CentOS7下安装最新版本的ELK,当然现在docker已经有完全配置成功的elk容器,安装配 ...

  4. 微信小程序里的bug---video 的play()

    微信小程序hidden转换后执行play()用真机测试不会播放.在调试器里可以. 解决方法,把hidden换成wx:if. 我刚开始以为网速问题,其实不是, 具体我也不知道为什,换上wxif解决了.

  5. 秒杀ecshop的前台写shell 0day

    ECSHOP号称最大的开源网店系统,官方是这样介绍它的:“ECShop网店系统是一套免费开源的网上商店软件,无论在稳定性.代码优化.运行效率.负载能力.安全等级.功能可操控性和权限严密性等方面都居国内 ...

  6. c语言,以单词为单位逆序字符串

    #include "string.h" #include "stdio.h" char * nixu(char *c) { ; int n = strlen(c ...

  7. eclipse maven工程打包失败

    报错如下: Maven install失败 Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:comp ...

  8. C# string contains 不区分大小写

    一种方法是把字符串转成小写/大写,然后包含的字符串也写成小写 /大写 另一种方法是: 1 string title = "STRING"; 2 bool contains = ti ...

  9. 用jieba库统计文本词频及云词图的生成

    一.安装jieba库 :\>pip install jieba #或者 pip3 install jieba 二.jieba库解析 jieba库主要提供提供分词功能,可以辅助自定义分词词典. j ...

  10. 线性表->应用->一元多项式

    文字描述 在数学上,一个一元多项式可以按升幂写成如下形式. 它由n+1个系数唯一确定.因此,在计算机里,可以用一个线性表P来表示,P中每一项的指数i隐含在其系数pi的序号里.   但是在通常的应用中, ...