Atomic
CAS原语
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
在 x86 下的指令CMPXCHG实现了CAS,前置LOCK既可以达到原子性操作。截止2013,大部分多核处理器均支持CAS。
ABA 问题
public final int getAndSet(int newValue) {
for (;;) {
//先读取val=1
int current = get();
//线程被抢占
if (compareAndSet(current, newValue))
return current;
}
}
thread2 修改val=3,又修改回1。
thread1继续执行,发现期望值与“原值”(其实被修改过了)相同,完成CAS操作。
AtomicIntegerFieldUpdater<T>
AtomicLongFieldUpdater<T>
AtomicReferenceFieldUpdater<T,V>
是基于反射的原子更新字段的值。
相应的API也是非常简单的,但是也是有一些约束的。
(1)字段必须是volatile类型的!volatile到底是个什么东西。
(2)字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致。也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。但是对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。
(3)只能是实例变量,不能是类变量,也就是说不能加static关键字。
(4)只能是可修改变量,不能使final变量,因为final的语义就是不可修改。实际上final的语义和volatile是有冲突的,这两个关键字不能同时存在。
(5)对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; public class AtomicIntegerFieldUpdaterDemo { class DemoData{
public volatile int value1 = 1;
volatile int value2 = 2;
protected volatile int value3 = 3;
private volatile int value4 = 4;
}
AtomicIntegerFieldUpdater<DemoData> getUpdater(String fieldName) {
return AtomicIntegerFieldUpdater.newUpdater(DemoData.class, fieldName);
}
void doit() {
DemoData data = new DemoData();
System.out.println("1 ==> "+getUpdater("value1").getAndSet(data, 10));
System.out.println("3 ==> "+getUpdater("value2").incrementAndGet(data));
System.out.println("2 ==> "+getUpdater("value3").decrementAndGet(data));
System.out.println("true ==> "+getUpdater("value4").compareAndSet(data, 4, 5));
}
public static void main(String[] args) {
AtomicIntegerFieldUpdaterDemo demo = new AtomicIntegerFieldUpdaterDemo();
demo.doit();
}
}
在上面的例子中DemoData的字段value3/value4对于AtomicIntegerFieldUpdaterDemo类是不可见的,因此通过反射是不能直接修改其值的。
AtomicMarkableReference类描述的一个<Object,Boolean>的对,可以原子的修改Object或者Boolean的值,这种数据结构在一些缓存或者状态描述中比较有用。这种结构在单个或者同时修改Object/Boolean的时候能够有效的提高吞吐量。
AtomicStampedReference类维护带有整数“标志”的对象引用,可以用原子方式对其进行更新。对比AtomicMarkableReference类的<Object,Boolean>,AtomicStampedReference维护的是一种类似<Object,int>的数据结构,其实就是对对象(引用)的一个并发计数。但是与AtomicInteger不同的是,此数据结构可以携带一个对象引用(Object),并且能够对此对象和计数同时进行原子操作。
Atomic的更多相关文章
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- JUC学习笔记--Atomic原子类
J.U.C 框架学习顺序 http://blog.csdn.net/chen7253886/article/details/52769111 Atomic 原子操作类包 Atomic包 主要是在多线程 ...
- 原子类java.util.concurrent.atomic.*原理分析
原子类java.util.concurrent.atomic.*原理分析 在并发编程下,原子操作类的应用可以说是无处不在的.为解决线程安全的读写提供了很大的便利. 原子类保证原子的两个关键的点就是:可 ...
- 【iOS atomic、nonatomic、assign、copy、retain、weak、strong】的定义和区别详解
一.atomic与nonatomic 1.相同点 都是为对象添加get和set方法 2.不同点 atomic为get方法加了一把安全锁(及原子锁),使得方法get线程安全,执行效率慢 nonatomi ...
- OS中atomic的实现解析
OS中atomic的实现解析 转自:http://my.oschina.net/majiage/blog/267409 摘要 atomic属性线程安全,会增加一定开销,但有些时候必须自定义ato ...
- Objective-c的@property(atomic,nonatomic,readonly,readwrite,assign,retain,copy,getter,setter) 属性特性
assign:指定setter方法用简单的赋值,这是默认操作.你可以对标量类型(如int)使用这个属性.你可以想象一个float,它不是一个对象,所以它不能retain.copy. retain:指定 ...
- 为什么volatile不能保证原子性而Atomic可以?
在上篇<非阻塞同步算法与CAS(Compare and Swap)无锁算法>中讲到在Java中long赋值不是原子操作,因为先写32位,再写后32位,分两步操作,而AtomicLong赋值 ...
- Objective-C 关键字:retain, assgin, copy, readonly,atomic,nonatomic
声明式属性的使用:声明式属性叫编译期语法 @property(retain,nonatomic)Some *s; @property(参数一,参数二)Some *s; 参数1:retain:修饰引用( ...
- Java中的Atomic包
Atomic包的作用 方便程序员在多线程环境下,无锁的进行原子操作 Atomic包核心 Atomic包里的类基本都是使用Unsafe实现的包装类,核心操作是CAS原子操作: 关于CAS compare ...
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
synchronized: 在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的.原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不 ...
随机推荐
- css的一些小技巧!页面视觉差!
相当长的一段时间,现在网站与所谓的“视差”效果一直很受欢迎. 万一你没有听说过这种效果,不同的图像,在不同的方向移动或层主要包括.这导致了一个很好的光学效应,使参观者的注意. 在网页设计中,为了实现这 ...
- [转载]angularjs学习总结 详细教程
http://blog.csdn.net/yy374864125/article/details/41349417#t75 目录(?)[-] 前言 AngularJS概述 AngularJS是什么 A ...
- javascript将毫秒转换成hh:mm:ss的形式
function formatMilliseconds(value) { var second = parseInt(value) / 1000; // second var minute = 0; ...
- ruby on rails揭开route路由的真面目
文章是从我的个人主页上粘贴过来的, 大家也可以访问我的主页 www.iwangzheng.com 最近的项目里发现一个问题,大师和pp写的index页面就好使,我写index页面就不往index页面跳 ...
- [BZOJ1477]青蛙的约会
[BZOJ1477]青蛙的约会 试题描述 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘 ...
- HTML快速入门2
三.版面风格控制 1. 字体控制 A. 字体大小 用 <font Size=#> 和 </font> 表示,#为字号: 1 - 7 ,缺省为 3 ,可用 <basefon ...
- 推荐一个linux下的web压力测试工具神器webbench
推荐一个linux下的web压力测试工具神器webbench2014-04-30 09:35:29 来源: 评论:0 点击:880 用多了apache的ab工具之后你就会发现ab存在很多问题, ...
- Shell之date用法
创建以当前时间为文件名的 mkdir `date+%Y%m%d` 备份以时间做为文件名的 tar cvf./htdocs`date +%Y%m%d`.tar ./* date命令如何获得上星期的日期? ...
- 【OpenStack】OpenStack系列3之Swift详解
Swift安装部署(与keystone依赖包有冲突,需要安装不同版本eventlet) 参考:http://www.server110.com/openstack/201402/6662.html h ...
- 【SpringMVC】SpringMVC系列8之Servlet API 作为入参
8.Servlet API 作为入参 8.1.概述 MVC 的 Handler 方法可以接受哪些 ServletAPI 类型的参数: HttpServletRequest HttpServletRes ...