西北野狼
我的github: https://github.com/soyoungboy
我的segmentfault: http://segmentfault.com/u/soyoungboy
【不积跬步,无以至千里;不积小流,无以成江海】
博客园 首页 新随笔 联系 订阅
管理 随笔-477 评论-20 文章-0
【推荐】微信小程序一站式部署 多场景模板定制
最新IT新闻:
· 你逛的这些地方,可能都是腾讯的地盘
· 你已经习惯了的这些衣食住行,其实都是阿里的地盘
· 华为云总裁郑叶来:公有云竞争远未结束 AI被过度消费
· 扎克伯格纪念FB诞生14周年:你们想到的错误 我都犯过
· A站凉了,百万“猴子”无家可归
» 更多新闻...
最新知识库文章:
· 领域驱动设计在互联网业务开发中的实践
· 步入云计算
· 以操作系统的角度述说线程与进程
· 软件测试转型之路
· 门内门外看招聘
» 更多知识库文章... 昵称:西北野狼
园龄:4年6个月
粉丝: 34
关注: 3 +加关注
我的github: https://github.com/soyoungboy
我的segmentfault: http://segmentfault.com/u/soyoungboy
【不积跬步,无以至千里;不积小流,无以成江海】
博客园 首页 新随笔 联系 订阅
管理 随笔-477 评论-20 文章-0
java多线程 -- 原子量 变量 CAS
多线程原子性问题的产生和解决
原子变量:在 java.util.concurrent.atomic 包下提供了一些原子变量。
1. volatile 保证内存可见性,可以查看atomic中变量是使用volatile来进行修饰的:
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
/**
* Creates a new AtomicInteger with the given initial value.
*
* @param initialValue the initial value
*/
public AtomicInteger(int initialValue) {
value = initialValue;
}
2. CAS(Compare-And-Swap)比较并交换,算法保证数据变量的原子性
CAS 算法是硬件对于并发操作的支持
CAS 包含了三个操作数:
①内存值 V
②预估值 A
③更新值 B
当且仅当 V == A 时, V = B; 否则,不会执行任何操作。
模拟CAS算法:
/*
* 模拟 CAS 算法
*/
public class TestCompareAndSwap {
public static void main(String[] args) {
final CompareAndSwap cas = new CompareAndSwap();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int expectedValue = cas.get();
boolean b = cas.compareAndSet(expectedValue, (int)(Math.random() * 101));
System.out.println(b);
}
}).start();
}
}
}
class CompareAndSwap{
private int value;
//获取内存值
public synchronized int get(){
return value;
}
//比较
public synchronized int compareAndSwap(int expectedValue, int newValue){
int oldValue = value;
if(oldValue == expectedValue){
this.value = newValue;
}
return oldValue;
}
//设置
public synchronized boolean compareAndSet(int expectedValue, int newValue){
return expectedValue == compareAndSwap(expectedValue, newValue);
}
}
其他博文关于CAS的详细描述:http://blog.csdn.net/ls5718/article/details/52563959
- AtomicBoolean 可以用原子方式更新的 boolean 值。
- AtomicInteger 可以用原子方式更新的 int 值。
- AtomicIntegerArray 可以用原子方式更新其元素的 int 数组。
- AtomicIntegerFieldUpdater<T> 基于反射的实用工具,可以对指定类的指定 volatile int 字段进行原子更新。
- AtomicLong 可以用原子方式更新的 long 值。
- AtomicLongArray 可以用原子方式更新其元素的 long 数组。
- AtomicLongFieldUpdater<T> 基于反射的实用工具,可以对指定类的指定 volatile long 字段进行原子更新。
- AtomicMarkableReference<V> AtomicMarkableReference 维护带有标记位的对象引用,可以原子方式对其进行更新。
- AtomicReference<V> 可以用原子方式更新的对象引用。
- AtomicReferenceArray<E> 可以用原子方式更新其元素的对象引用数组。
- AtomicReferenceFieldUpdater<T,V> 基于反射的实用工具,可以对指定类的指定 volatile 字段进行原子更新。
- AtomicStampedReference<V> AtomicStampedReference 维护带有整数“标志”的对象引用,可以用原子方式对其进行更新。
先看下AtomicInteger:
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by soyoungboy on 2017/3/28.
*/
public class AtomicDemo {
public static void main(String[] args) {
testAtomicInteger();
}
private static void testAtomicInteger() {
AtomicInteger atomicInteger = new AtomicInteger(1);
//get()获取当前值。
int x = atomicInteger.get();
System.out.println("get()获取当前值 = " + x);
//addAndGet(int delta)以原子方式将给定值与当前值相加
int i = atomicInteger.addAndGet(2);
System.out.println("addAndGet(int delta)以原子方式将给定值与当前值相加 = " + i);
// decrementAndGet()以原子方式将当前值减 1。
int i1 = atomicInteger.decrementAndGet();
System.out.println("decrementAndGet()以原子方式将当前值减 1 = " + i1);
//doubleValue() 以 double 形式返回指定的数值。
double doubleValue = atomicInteger.doubleValue();
System.out.println("doubleValue() 以 double 形式返回指定的数值。 = " + doubleValue);
//floatValue()以 float 形式返回指定的数值。
float floatValue = atomicInteger.floatValue();
System.out.println("floatValue()以 float 形式返回指定的数值。。 = " + floatValue);
// intValue() 以 int 形式返回指定的数值。
int intValue = atomicInteger.intValue();
System.out.println("intValue() 以 int 形式返回指定的数值。= " + intValue);
//etAndSet(int newValue)以原子方式设置为给定值,并返回旧值。
int andAdd = atomicInteger.getAndAdd(20);
System.out.println("---------------------------------------------------------");
System.out.println("getAndAdd(int delta)以原子方式将给定值与当前值相加。旧值 = " + andAdd);
System.out.println("新值 = " + atomicInteger.get());
System.out.println("---------------------------------------------------------");
//getAndDecrement()以原子方式将当前值加 1。
int andDecrement = atomicInteger.getAndDecrement();
System.out.println("getAndDecrement()以原子方式将当前值减 1。 = " + andDecrement);
//getAndDecrement()以原子方式将当前值减 1。
int andIncrement = atomicInteger.getAndIncrement();
System.out.println("getAndDecrement()以原子方式将当前值减 1。" + andIncrement);
//以原子方式将当前值加 1。
int incrementAndGet = atomicInteger.incrementAndGet();
System.out.println("以原子方式将当前值加 1。" + incrementAndGet);
}
}
结果:
get()获取当前值 = 1
addAndGet(int delta)以原子方式将给定值与当前值相加 = 3
decrementAndGet()以原子方式将当前值减 1 = 2
doubleValue() 以 double 形式返回指定的数值。 = 2.0
floatValue()以 float 形式返回指定的数值。。 = 2.0
intValue() 以 int 形式返回指定的数值。= 2
---------------------------------------------------------
getAndAdd(int delta)以原子方式将给定值与当前值相加。旧值 = 2
新值 = 22
---------------------------------------------------------
getAndDecrement()以原子方式将当前值减 1。 = 22
getAndDecrement()以原子方式将当前值减 1。21
以原子方式将当前值加 1。23
原子更新数组
- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray<E>
/**
* Created by soyoungboy on 2017/3/28.
*/
public class AtomicDemo {
public static void main(String[] args) {
testAtomicInteger();
}
private static void testAtomicInteger() {
Person person = new Person(11,"小强");
Person person1 = new Person(11,"大强");
Person[] peoples = new Person[]{person,person1};
AtomicReferenceArray<Person> personAtomicReferenceArray = new AtomicReferenceArray<Person>(peoples);
printArray(personAtomicReferenceArray);
// 以原子方式将位置 i 的元素设置为给定值,并返回旧值。
Person person2 = new Person(22, "老秦");
Person andSet = personAtomicReferenceArray.getAndSet(1, person2);
System.out.println("返回的旧值 = "+andSet);
printArray(personAtomicReferenceArray);
//weakCompareAndSet(int i, E expect, E update)
// 如果当前值 == 预期值,则以原子方式将位置 i 的元素设置为给定的更新值。
Person person3 = new Person(23, "哈哈");
//因为上面替换为老秦的person,所以如果是老秦的person,就替换
personAtomicReferenceArray.weakCompareAndSet(1,person2,person3);
printArray(personAtomicReferenceArray);
}
private static void printArray(AtomicReferenceArray<Person> personAtomicReferenceArray) {
System.out.println("-------------------------------------");
for (int i = 0;i<personAtomicReferenceArray.length();i++){
String s = personAtomicReferenceArray.get(i).toString();
System.out.println(s);
}
}
}
结果:
-------------------------------------
Person{age=11, name='小强'}
Person{age=11, name='大强'}
返回的旧值 = Person{age=11, name='大强'}
-------------------------------------
Person{age=11, name='小强'}
Person{age=22, name='老秦'}
-------------------------------------
Person{age=11, name='小强'}
Person{age=23, name='哈哈'}
原子更新引用类型
- AtomicReference:原子更新引用类型。
- AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
- AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子更新一个布尔类型的标记位和引用类型。构造方法是AtomicMarkableReference(V initialRef,boolean initialMark)。
举例子:
import java.util.concurrent.atomic.AtomicReference;
/**
* Created by Administrator on 2017/3/28.
*/
public class AtomicReferenceDemo {
public static void main(String[] args) {
testAtomicReference();
}
private static void testAtomicReference() {
Person person1 = new Person(1,"姚明");
Person person2 = new Person(2,"易建联");
Person person3 = new Person(3,"王思聪");
AtomicReference<Person> personAtomicReference = new AtomicReference<>(person1);
System.out.println("personAtomicReference"+personAtomicReference.get().toString());
System.out.println("------------------------------------------------------------");
//compareAndSet(V expect, V update)如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
//person2肯定不是期望值,所以不会设置为person3,因此值应该为person1
personAtomicReference.compareAndSet(person2,person3);
System.out.println("personAtomicReference"+personAtomicReference.get().toString());
System.out.println("------------------------------------------------------------");
// getAndSet(V newValue) 以原子方式设置为给定值,并返回旧值。
Person andSet = personAtomicReference.getAndSet(person2);
System.out.println("旧值 = "+andSet);
System.out.println("新值 = "+personAtomicReference.get().toString());
personAtomicReference.lazySet(person3);
//lazySet(V newValue)最终设置为给定值。
System.out.println("lazySet "+personAtomicReference.get().toString());
}
}
结果:
personAtomicReferencePerson{age=1, name='姚明'}
------------------------------------------------------------
personAtomicReferencePerson{age=1, name='姚明'}
------------------------------------------------------------
旧值 = Person{age=1, name='姚明'}
新值 = Person{age=2, name='易建联'}
lazySet Person{age=3, name='王思聪'}
原子更新字段类
- AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
- AtomicLongFieldUpdater:原子更新长整型字段的更新器。
- AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于原子的更新数据和数据的版本号,可以解决使用CAS进行原子更新时可能出现的ABA问题。
newUpdater(Class<U> tclass, String fieldName)
使用给定字段为对象创建和返回一个更新器。
这是这个不同于上面类的方法,其他基本上一样。
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
/**
* Created by Administrator on 2017/3/28.
*/
public class AtomicIntegerFieldUpdaterDemo {
public static void main(String[] args) {
testAtomicReference();
}
private static void testAtomicReference() {
Person person1 = new Person(1,"姚明");
AtomicReferenceFieldUpdater<Person, String> atomicReferenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(
Person.class, String.class, "name");
// 如果当前值 == 预期值,则以原子方式将此更新器管理的给定对象的字段设置为给定的更新值。
atomicReferenceFieldUpdater.compareAndSet(person1,person1.name,"哈哈");
System.out.println("person1 = "+person1.toString());
AtomicReferenceFieldUpdater<Person, Integer> atomicReferenceFieldUpdater1 = AtomicReferenceFieldUpdater.newUpdater(
Person.class, Integer.class, "age");
// 如果当前值 == 预期值,则以原子方式将此更新器管理的给定对象的字段设置为给定的更新值。
atomicReferenceFieldUpdater1.compareAndSet(person1,person1.age,22);
System.out.println("person1 = "+person1.toString());
}
}
结果:
person1 = Person{age=1, name='哈哈'}
person1 = Person{age=22, name='哈哈'}
posted on 2017-03-19 17:48 西北野狼 阅读(42) 评论(0) 编辑 收藏 刷新评论刷新页面返回顶部 注册用户登录后才能发表评论,请 登录 或 注册, 访问网站首页。 【推荐】超50万VC++源码: 大型工控、组态\仿真、建模CAD源码2018!
【推荐】微信小程序一站式部署 多场景模板定制
最新IT新闻:· 你逛的这些地方,可能都是腾讯的地盘
· 你已经习惯了的这些衣食住行,其实都是阿里的地盘
· 华为云总裁郑叶来:公有云竞争远未结束 AI被过度消费
· 扎克伯格纪念FB诞生14周年:你们想到的错误 我都犯过
· A站凉了,百万“猴子”无家可归
» 更多新闻...
最新知识库文章:· 领域驱动设计在互联网业务开发中的实践
· 步入云计算
· 以操作系统的角度述说线程与进程
· 软件测试转型之路
· 门内门外看招聘
» 更多知识库文章... 昵称:西北野狼
园龄:4年6个月
粉丝: 34
关注: 3 +加关注
|
||||||
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
|---|---|---|---|---|---|---|
| 28 | 29 | 30 | 31 | 1 | 2 | 3 |
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 1 | 2 | 3 |
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
搜索
常用链接
我的标签
- android 5.0(16)
- ormlite(3)
- AndroidGradle(2)
- java复习(2)
- swift object c学习(1)
- Swift or Object c(1)
随笔分类
- 【android 面试】(12)
- 【android】(194)
- 【android--bug】(33)
- 【android--openGL】(1)
- 【androidstudio--学习和使用经验】(2)
- 【android--Thread--线程池的使用】(1)
- 【android--性能优化】(19)
- 【App研发录读书笔记】(6)
- 【Effactive Java】(2)
- 【Eventbus】(7)
- 【Gradle学习】
- 【html5】(6)
- 【IOS】(3)
- 【J2EE】(22)
- 【J2EE面试题】(2)
- 【Java -- JDBC 学习】(12)
- 【java 1.8 新特性学习】
- 【Java NIO -- IO高级进阶】(7)
- 【java 基础复习】(5)
- 【JavaWeb】(2)
- 【java多线程 -- 高级进阶】(10)
- 【JDK源码学习】(2)
- 【json异常】(2)
- 【maven学习】(4)
- 【MySQL】(1)
- 【phoneGap学习】(1)
- 【python 学习】(11)
- 【Rxjava学习】(1)
- 【Servlet】(2)
- 【shell脚本学习】
- 【sqlite高级进阶】(1)
- 【Volley学习和源码分析】(7)
- 【Web前端 -- JavaScript 学习和复习】(8)
- 【Web前端--Html&Css学习复习】(39)
- 【产品知识学习】
- 【计划】(1)
- 【设计模式复习】(26)
- 【深入理解java虚拟机】(2)
- 【数据结构与算法】(6)
- 【移动支付】(3)
- 【重构-改善既有代码的设计】
- 【自定义控件】(7)
随笔档案
- 2017年11月 (3)
- 2017年10月 (8)
- 2017年9月 (9)
- 2017年8月 (11)
- 2017年7月 (4)
- 2017年6月 (26)
- 2017年5月 (22)
- 2017年4月 (40)
- 2017年3月 (18)
- 2017年2月 (11)
- 2017年1月 (9)
- 2016年9月 (5)
- 2016年8月 (6)
- 2016年7月 (2)
- 2016年6月 (4)
- 2016年5月 (7)
- 2016年4月 (8)
- 2016年3月 (2)
- 2016年2月 (2)
- 2016年1月 (2)
- 2015年12月 (6)
- 2015年11月 (10)
- 2015年10月 (10)
- 2015年9月 (11)
- 2015年8月 (5)
- 2015年7月 (13)
- 2015年6月 (6)
- 2015年5月 (17)
- 2015年4月 (10)
- 2015年3月 (6)
- 2015年2月 (4)
- 2015年1月 (19)
- 2014年12月 (15)
- 2014年11月 (11)
- 2014年10月 (1)
- 2014年9月 (2)
- 2014年8月 (4)
- 2014年7月 (2)
- 2014年6月 (2)
- 2014年5月 (17)
- 2014年4月 (11)
- 2014年3月 (6)
- 2014年2月 (4)
- 2014年1月 (17)
- 2013年12月 (38)
- 2013年11月 (21)
- 2013年10月 (2)
- 2013年9月 (1)
- 2013年8月 (7)
My github
我的个人博客站点
积分与排名
- 积分 - 110533
- 排名 - 2676
最新评论
- 1. Re:J2EE--常见面试题总结 -- 一
- mark
- --Jason928
- 2. Re:LinkedHashMap 源码解析
- @稻花谢谢,也欢迎多多指点和建议...
- --西北野狼
- 3. Re:LinkedHashMap 源码解析
- 非常不错
- --稻花
- 4. Re:项目实战之集成邮件开发
- 不错!
- --天边里
- 5. Re:Spring -- AOP
- @BillySir通过 ProceedingJoinPoint 或者JoinPoint...
- --西北野狼
阅读排行榜
- 1. Glide加载圆形图片(13832)
- 2. androidstudio--gsonformat--超爽的数据解析方式(9863)
- 3. android app 集成 支付宝支付 微信支付(6304)
- 4. 项目中处理android 6.0权限管理问题(4390)
- 5. Activity生命周期方法调用finish后的不同表现(4353)
评论排行榜
- 1. material design 的android开源代码整理(4)
- 2. Spring -- AOP(2)
- 3. 如何在使用eclipse的情况下,清理android项目中的冗余class文件和资源文件以及冗余图片(2)
- 4. android使用shape做selector按钮按下和弹起的动画(2)
- 5. java泛型操作复习,以及讲解在android中使用的场景(2)
推荐排行榜
- 1. material design 的android开源代码整理(8)
- 2. 某技术大牛的帖子(android项目总结)(1)
- 3. android经典开源代码集合(1)
- 4. android -- 加载gif 防止oom(1)
- 5. android 实现透明状态栏(1)