- 浏览: 130473 次
- 性别:
- 来自: ...
文章分类
最新评论
之前看到一个帖子是关于atomic使用的,当时没有仔细分析问题,理解有误,作者回信给我,我又去看了一下.原来的问题大致如下:
这样的写法能保证同步吗?按照这个写法的话,if块一定要使用同步锁保证同步的.但是那样的话Atomic的优势将大打折扣,代码的主要问题不在if而在if内的那句赋值:longValue = new AtomicLong(0).
重新new出Atomic实例+同步锁的双重成本,可能会使代码执行的性能不尽如人意.所以我昨天想了一下,要保证同步又不使用锁其实利用Atomic的CAS应该是能做到的.写了一个小例子:
这里我把AtomicLong的实例定义成final的,避免了实例化的开销.incrementOrClear()方法的作用就是递增或者清零.首先从理论上的保证是所有对AtomicLong的实例longValue的操作都是CAS的,所以其不会出现重复赋值的现象.这里我开了两个测试线程,循环调用incrementOrClear()方法,两个线程在方法内1,2处的情况分析如下:
1.线程A,B都处于2处,有两个可能:(1)线程A,B的局部变量var相同,这时候有一个线程的CAS成功,另一个的var就会与longValue的最新值不同,CAS失败,保证了不重复写.(2)线程A,B的var不同,例如线程A的var=7之后A暂缓,B线程一直CAS直到其var=30时A继续执行,A,B同时进入2.这个时候线程A的CAS显然要失败,因为longValue的最新值是30,而B的CAS成功,保证了longValue的递增,同时A再次调用方法时,var的值被同步到最新的值.
2.线程A,B都处于1处,这是只有一种可能就是两者的var都是50,此时也是只有一个线程能够成功的执行longValue的CAS操作使其清零.
3.线程A,B分布在1,2两处.那么拥有与longValue的最新值一致的var会成功执行CAS操作.假设A在1处,B在2处.A的var=50,B的var=49.若longValue的最新值是50则清零成功.若longValue的最新值是49,这种情况是A的var=50时被暂缓了,B执行了清零并且新循环到49.这个时候依然是B的CAS成功,A的清零失败.即使此时B被暂缓了,那么A也会失败之后再次调用方法更新var的值替代B执行递增.如果恰好循环到B暂缓时的var值时B也继续执行了,那么就是分析1的情况(1).
所以上述的分析,我认为任何情况都包括在内了,能够保证无锁机制的同步.并且实际运行也能体现了特别是3的分析:线程的,与longValue最新值不同的,var值再次打印时会被刷新而不是递增破坏longValue的唯一性.通过这个机会再次认识Atomic的CAS,我想还是有必要记录一下的.在此感谢作者的回复.
private AtomicLong longValue = new AtomicLong(0); if(longValue.incrementAndGet() > 50) { longValue = new AtomicLong(0); }
这样的写法能保证同步吗?按照这个写法的话,if块一定要使用同步锁保证同步的.但是那样的话Atomic的优势将大打折扣,代码的主要问题不在if而在if内的那句赋值:longValue = new AtomicLong(0).
重新new出Atomic实例+同步锁的双重成本,可能会使代码执行的性能不尽如人意.所以我昨天想了一下,要保证同步又不使用锁其实利用Atomic的CAS应该是能做到的.写了一个小例子:
public class AtomicCounterSample { private final AtomicLong longValue = new AtomicLong(0); public void incrementOrClear() { // String name = Thread.currentThread().getName(); long var = longValue.get(); if(var >= 50) { longValue.compareAndSet(var,0); // 1 } else { // System.out.println(name + ": " + var); longValue.compareAndSet(var,var + 1l); // 2 } } public static void main(String[] args) { final AtomicCounterSample sample = new AtomicCounterSample(); Thread threada = new Thread(new Runnable() { public void run() { for(int i = 0; i < 100; i++) { sample.incrementOrClear(); } } }); threada.setName("A"); Thread threadb = new Thread(new Runnable() { public void run() { for(int i = 0; i < 150; i++) { sample.incrementOrClear(); } } }); threadb.setName("B"); threada.start(); threadb.start(); } }
这里我把AtomicLong的实例定义成final的,避免了实例化的开销.incrementOrClear()方法的作用就是递增或者清零.首先从理论上的保证是所有对AtomicLong的实例longValue的操作都是CAS的,所以其不会出现重复赋值的现象.这里我开了两个测试线程,循环调用incrementOrClear()方法,两个线程在方法内1,2处的情况分析如下:
1.线程A,B都处于2处,有两个可能:(1)线程A,B的局部变量var相同,这时候有一个线程的CAS成功,另一个的var就会与longValue的最新值不同,CAS失败,保证了不重复写.(2)线程A,B的var不同,例如线程A的var=7之后A暂缓,B线程一直CAS直到其var=30时A继续执行,A,B同时进入2.这个时候线程A的CAS显然要失败,因为longValue的最新值是30,而B的CAS成功,保证了longValue的递增,同时A再次调用方法时,var的值被同步到最新的值.
2.线程A,B都处于1处,这是只有一种可能就是两者的var都是50,此时也是只有一个线程能够成功的执行longValue的CAS操作使其清零.
3.线程A,B分布在1,2两处.那么拥有与longValue的最新值一致的var会成功执行CAS操作.假设A在1处,B在2处.A的var=50,B的var=49.若longValue的最新值是50则清零成功.若longValue的最新值是49,这种情况是A的var=50时被暂缓了,B执行了清零并且新循环到49.这个时候依然是B的CAS成功,A的清零失败.即使此时B被暂缓了,那么A也会失败之后再次调用方法更新var的值替代B执行递增.如果恰好循环到B暂缓时的var值时B也继续执行了,那么就是分析1的情况(1).
所以上述的分析,我认为任何情况都包括在内了,能够保证无锁机制的同步.并且实际运行也能体现了特别是3的分析:线程的,与longValue最新值不同的,var值再次打印时会被刷新而不是递增破坏longValue的唯一性.通过这个机会再次认识Atomic的CAS,我想还是有必要记录一下的.在此感谢作者的回复.
发表评论
文章已被作者锁定,不允许评论。
-
一道位操作的趣味编程题
2010-03-14 10:50 2080看到一道很有意思的编程题:大厅里有64盏灯,每盏灯都编 ... -
一道字符串截取的编程题
2010-03-11 10:52 2272最近接触到一道字符串截取的编程题:编写一个截取字符串的 ... -
一道多线程趣味热身题
2010-02-28 18:01 1912保持对知识点或者技术的熟悉度对于程序员至关重要,要学会 ... -
疑似Google多线程面试题的Java实现
2010-02-24 17:39 4904来到一个完全陌生的地方,即将一切从新开始,内心兴奋又忐 ... -
Mina的线程池实现分析(2)
2010-02-10 17:31 4517分析了I/O事件的存储,下面看看多个Worker同时工 ... -
Mina的线程池实现分析(1)
2010-02-10 17:28 11571线程池是并发应用中,为了减少每个任务调用的开销增强性能 ... -
多线程基础总结十一--ConcurrentLinkedQueue
2010-02-03 17:52 12835ConcurrentLinkedQueue充分使用了a ... -
LinkedBlockingQueue应用--生产消费模型简单实现
2010-01-29 20:45 8134之前介绍时LinkedBlockingQueue提到了 ... -
多线程基础总结十--LinkedBlockingQueue
2010-01-28 14:33 15369随着多线程基础总结的增多,却明显的感觉知道的越来越少, ... -
号称放倒一片的一道J2SE基础题的个人理解
2010-01-23 14:07 2788近日无意中看到一道Java基础题,号称在接受测试的10 ... -
多线程基础总结九--Mina窥探(1)
2010-01-21 23:46 5394一直以来的多线程的基础总结都是脱离应用的,但是要说多线 ... -
多线程基础总结八--ReentrantReadWriteLock
2010-01-15 23:22 7506说到ReentrantReadWriteLock,首先 ... -
多线程基础总结七--ReentrantLock
2010-01-09 23:17 7674之前总结了部分无锁机制的多线程基础,理想的状态当然是利 ... -
多线程基础总结六--synchronized(2)
2009-12-18 18:45 1866早在总结一时,我就尽量的把synchronized的重点 ... -
多线程基础总结五--atomic
2009-12-17 19:46 3546在简单介绍java.util.c ... -
多线程基础总结四--ThreadLocal
2009-12-16 19:48 2716说到ThreadLocal,首先 ... -
多线程基础总结三--volatile
2009-12-15 20:09 2522前面的两篇总结简 ... -
多线程基础总结二--Thread
2009-12-12 23:27 2664对于Thread来说 ... -
多线程基础总结一--synchronized(1)
2009-12-12 23:23 3066最近写关于并发的小应 ... -
由destory-method引发的IOC容器设计的思考
2009-12-07 16:51 1678第一次读Spring的源 ...
相关推荐
atomic
Atomic
Atomic Scala eBook 编程思想的作者新书
主要研究四种变量(属性)的存取速度. volatile nonatomic atomic和正常变量
Atomic clock radio
前端开源库-atomic-batcher原子批处理程序,一个简单的批处理函数,允许您自动批处理一系列操作。
来自BOOST库的原子操作atomic的源代码,跨平台
不错的时钟工具,带闹铃,日历,可置顶 Atomic Alarm Clock.rar
atomic_ops原子操作1
ATOMIC:an atlas of machine commonsense for if-then reasoning中的数据集
Atom-Atomic-Monokai-Syntax.zip,A Monokai-flavored syntax highlighting theme for Atom作为一个长期的优秀文本用户,我已经过渡到使用atom作为我的代码编辑器,虽然我喜欢它更易破解的方面,但我并没有找不到一个...
Atomic bitops based version of ext2 atomic bitops.
描述了linux系统原子操作的实现以及使用原子操作时的注意事项。
Atomic CSS增量更新的设计与实现,刘灿,沈奇威,(1)针对Atomic CSS全量更新过程中耗费时间、流量较大的问题,提出一种增量更新方案。该方案将CSS内容与版本信息分别保存于浏览器Loca
ZooKeeper’s atomic broadcast protocol 翻译版
dll控件常规安装方法(仅供参考): 一、如果在运行某软件或编译程序时提示缺少、找不到dll等类似提示,您可将下载来的dll拷贝到指定目录即可(一般是system系统目录或放到软件同级目录里面),或者重新添加文件引用...
Introduction to quantum optics and modern atomic physics. The basic concepts and theoretical tools will be introduced. Topics will include coherence phenomena, non-classical states of light and matter...
Atom-atomic-blonde.zip,SourceKit-based syntax highlighting for the Swift languageAtomic Blonde是一种基于SourceKit的用于Swift语言的语法增强器。与由正则表达式语法支持的highlighter不同,atomic blonde调用...
英文版带目录
angular-atomic-notify, angular.js 应用程序的原子咆哮通知 angular-atomic-notify一个用于显示通知的AngularJS模块 依赖项我们使用这个库作为示例,注意jQuery用于 angular.element 和 Font Awesome 图标,但是你...