java多线程之CAS
来源:互联网 发布:计算机美工 编辑:程序博客网 时间:2024/06/04 20:31
CAS操作
在java中可以通过锁和CAS操作来实现操作的原子性。cas即compare and set的缩写。JVM中的CAS操作利用了处理器提供的CMPXCHG指令实现。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止。下面的代码展示的是如何通过CAS算法来实现线程同步:
package chapter02;import java.util.ArrayList;import java.util.List;import java.util.concurrent.atomic.AtomicInteger;public class CAS { //使用java concurrent包中的AtomicInteger类来实现CAS操作 private AtomicInteger atomic = new AtomicInteger(0); //非线程安全的变量i private int i = 0; public static void main(String args[]) { final CAS cas = new CAS(); List<Thread> ts = new ArrayList<Thread>(600); long start = System.currentTimeMillis(); for (int i = 0; i < 100; i++) { Thread t = new Thread(new Runnable() { @Override public void run() { for(int j=0;j<10000;j++){ cas.count(); cas.safeCount(); } } }); ts.add(t); } for(Thread t :ts){ t.start(); } for(Thread t:ts){ try{ t.join(); }catch(Exception e){ e.printStackTrace(); } } System.out.println("unsafe"+cas.i); System.out.println("safe"+cas.atomic.get()); System.out.println(System.currentTimeMillis()-start); } //线程安全的Count方法 private void safeCount() { for (;;) { //atomic的get()方法获取volatile变量value int i = atomic.get(); //如果设置成功,则获得运行权,否则所有的线程都通过自旋的方法获取执行权 boolean suc = atomic.compareAndSet(i, ++i); if (suc) { break; } } } //非线程安全的count方法 private void count() { i++; }}
上面的代码运行结构为:
unsafe834081
safe1000000
87
CAS原理:
通过查看AtomicInteger的源码可知,
`private volatile int value;
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}`
通过申明一个volatile (内存锁定,同一时刻只有一个线程可以修改内存值)类型的变量,再加上unsafe.compareAndSwapInt的方法,来保证实现线程同步的。
缺点:
1、ABA问题
CAS操作容易导致ABA问题,也就是在做a++之间,a可能被多个线程修改过了,只不过回到了最初的值,这时CAS会认为a的值没有变。a在外面逛了一圈回来,你能保证它没有做任何坏事,不能!!也许它讨闲,把b的值减了一下,把c的值加了一下等等,更有甚者如果a是一个对象,这个对象有可能是新创建出来的,a是一个引用呢情况又如何,所以这里面还是存在着很多问题的,解决ABA问题的方法有很多,可以考虑增加一个修改计数,只有修改计数不变的且a值不变的情况下才做a++,也可以考虑引入版本号,当版本号相同时才做a++操作等,这和事务原子性处理有点类似!
2、比较花费CPU资源,即使没有任何争用也会做一些无用功。
3、会增加程序测试的复杂度,稍不注意就会出现问题。
总结:
可以用CAS在无锁的情况下实现原子操作,但要明确应用场合,非常简单的操作且又不想引入锁可以考虑使用CAS操作,当想要非阻塞地完成某一操作也可以考虑CAS。不推荐在复杂操作中引入CAS,会使程序可读性变差,且难以测试,同时会出现ABA问题。
- java多线程之CAS
- 《Java多线程之CAS》
- java多线程之CAS
- java多线程之CAS
- java多线程之CAS详解
- Java多线程之AtomicReference,CAS
- java多线程(2)之CAS操作
- 多线程之CAS
- Java多线程: CAS
- 【Java多线程】CAS算法
- java--多线程--CAS
- Java之CAS操作
- Java学习之CAS
- java并发之CAS
- Java多线程---CAS和锁优化
- JAVA CAS 原子类及多线程总结
- Java多线程/并发17、简述CAS 操作
- Java多线程系列10(CAS)
- Linux命令
- vi/vim 光标移动命令
- Win7可变对象头结构之InfoMask解析
- iOS 获取手机的型号,系统版本,软件名称,软件版本
- appstore和腾讯的Entitlements
- java多线程之CAS
- 在 SQL Server 2008 中新建用户登录并指定该用户的数据库
- ios签名机制的理解
- PHP代码优化的方法
- DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
- sql修改字段长度
- AndroidStudio(2.0 Beta 6) 如何将新建的工程放到GitHub上
- 能正确下载ftp文件,但是文件内容为空大小为0
- Leetcode:242. Valid Anagram(JAVA)