(转)利用CAS算法实现通用线程安全状态机
在多线程环境下,如果某个类是有状态的,那我们在使用前,需要保证所有该类的实例对象状态一致,否则会出现意向不到的bug。下面是通用线程安全状态机的实现方法。
public class ThreadSaveState{
private int x;
private int y;
private enum State {NEW, INITIALIZING, INITIALIZED};
private final AtomicReference<State> init = new AtomicReference<State>(State.NEW);
public ThreadSaveState() {
};
public ThreadSaveState(int x, int y) {
initialize(x, y);
}
private void initialize(int x, int y) {
if (!init.compareAndSet(State.NEW, State.INITIALIZING)) {
throw new IllegalStateException("Already initialized");
}
this.x = x;
this.y = y;
//… Do anything else the original constructor did
init.set(State.INITIALIZED);
}
//所有公共接口,都要先调用该方法检测对象完整性
private void checkInit() {
if (init.get() != State.INITIALIZED) {
throw new IllegalStateException("Uninitialized");
}
}
//示例公用接口
public int getX() {
checkInit();
return x;
}
//示例公用接口
public int getY() {
checkInit();
return y;
}
}
这种模式利用compareAndSet方法来操作枚举的原子引用,关于compareAndSet方法,其内部是CAS算法,即:Compare and Swap, 翻译成比较并交换,源码如下:
java.util.concurrent包中借助CAS实现了区别于synchronouse同步锁的一种乐观锁,使用这些类在多核CPU的机器上会有比较好的性能.
结合compareAndSet源码我们看下:
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
* @param expect the expected value
* @param update the new value
* @return true if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
根据注释,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,返回True,否则返回false。
再看看我们初始化的代码:
if (!init.compareAndSet(State.NEW, State.INITIALIZING)) {
throw new IllegalStateException("Already initialized");
}
只有当state是New的时候,才开始初始化,否则直接报错。这就保证了对象的完整性,因为如果没有这样的防范机制,万一有个线程要在某个实例上调用initialize(),而另一个线程又要企图使用这个实例,第二个线程就有可能看到这个实例处于不一致的状态。
转载:http://blog.csdn.net/qq_27258799
(转)利用CAS算法实现通用线程安全状态机的更多相关文章
- 利用双重检查锁定和CAS算法:解决并发下数据库的一致性问题
背景 最近有一个场景遇到了数据库的并发问题.现在先由我来抽象一下,去掉不必要的繁杂业务. 数据库表book存储着每本书的阅读量,一开始数据库是空的,不存在任何的数据.当用户访问接口的时候,判断 ...
- (一)juc线程高级特性——volatile / CAS算法 / ConcurrentHashMap
1. volatile 关键字与内存可见性 原文地址: https://www.cnblogs.com/zjfjava/category/979088.html 内存可见性(Memory Visibi ...
- Java多线程系列——原子类的实现(CAS算法)
1.什么是CAS? CAS:Compare and Swap,即比较再交换. jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronou ...
- 并发策略-CAS算法
对于并发控制而言,我们平时用的锁(synchronized,Lock)是一种悲观的策略.它总是假设每一次临界区操作会产生冲突,因此,必须对每次操作都小心翼翼.如果多个线程同时访问临界区资源,就宁可牺牲 ...
- Compare and Swap [CAS] 算法
一个Java 5中最好的补充是对原子操作的支持类,如AtomicInteger,AtomicLong等.这些类帮助你减少复杂的(不必要的)多线程代码,实际上只是完成一些基本操作,如增加或减少多个线程之 ...
- 三、原子变量与CAS算法
原子变量:jdk1.5 后 java.util.concurrent.atomic 包下提供了常用的原子变量: - AtomicBoolean - AtomicInteger - AtomicLong ...
- 原子变量与CAS算法(二)
一.锁机制存在的问题 (1)在多线程竞争下,加锁.释放锁会导致比较多的上下文切换和调度延时,引起性能问题. (2)一个线程持有锁会导致其它所有需要此锁的线程挂起. (3)如果一个优先级高的线程等待一个 ...
- 原子性 CAS算法
一. i++ 的原子性问题 1.问题的引入: i++ 的实际操作分为三个步骤:读--改--写 实现线程,代码如下: public class AtomicDemo implements Runnabl ...
- java CAS算法
CAS算法是硬件对于并发操作的支持,其中包含了三个操作数:内存值,预估值和更新值.没当要执行更新操作时,会先在同步方法中比较内存值和预估值是否相等,如果相等才会用更新值替换内存值,否则什么也不做. p ...
随机推荐
- DWM1000 巧用Status 快速Debug
在Debug DWM1000 的时候,可以巧用Status 加快Debug,例如如下代码 if (status_reg & SYS_STATUS_RXFCG) { …… } else { sp ...
- java 实现加密算法(在网上看的,保存)
import java.util.ArrayList; import java.util.List; /** * DES加密/解密 * * @Copyright Copyr ...
- (52)Wangdao.com第七天_字面量/变量_标识符_数据类型_数据的存储
JavaScript 字面量 和 变量 字面量:就是那些不可变的值,如1,2,100,2000,Infinity,NaN 变量: 变量,代表的当前随机分配的内存地址. 变量的值,是可变的,可以用来保存 ...
- ecshop 2.x 3.x sql injection/rce payload
首先,感谢ringk3y的分析:http://ringk3y.com/2018/08/31/ec ... %E6%89%A7%E8%A1%8C/ 大家跟一遍代码基本上都能弄明白漏洞的原理,整个漏洞的构 ...
- 使用Java程序读取JPG Tif等格式图片的exif信息
package com.util; import java.io.File;import java.util.Iterator; import com.drew.imaging.ImageProces ...
- 微信小程序开发的游戏《拼图游戏》
微信小程序开发的游戏<拼图游戏> 代码直接考进去就能用 pintu.js // pintu.js Page({ /** * 页面的初始数据 */ data: { }, initGame: ...
- uc/os iii移植到STM32F4---IAR开发环境
也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢 ...
- 使用docker搭建centos虚拟机
网上有很多安装linux的,这里不记录; windows安装docker 转自:https://www.cnblogs.com/samwu/p/10360943.html(windows是家庭版的) ...
- masonry布局说明
这个要根据情况而定,有时会很有用的. setContentHuggingPriority: 优先级越高,代表压缩越厉害,越晚被拉伸.就是上图中那人拉的力量更强. setContentCompressi ...
- linux CentOS 安装 nginx+tomcat+java+mysql运行环境
本文介绍了CentOS7 64 Java,Tomcat,MySQL,Maven热部署等服务器环境的搭建过程. 服务器: 已经将所需要的工具(Xshell,Xftp.FileZilla等sftp上传工具 ...