第二章中,书中代码有一段用的CAS(Compare And Swap)实现了原子操作,由于我自己大致看了一遍代码,就用自己的理解写了一遍,运行一下就通了,比较了一下和书中的代码,除了安全计数那里稍有不同,其它部分差不多是一致。 安全计数的demo
package com.evan.concurrent.safeCount;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by evan on 3/20/17.
*/
public class SafeCountTest {
public static void main(String[] args) throws Exception{
long startTime = System.currentTimeMillis();
int totalCount = 3000;
final CountDownLatch countDownLatch = new CountDownLatch(totalCount);
for(int i=0;i<totalCount;i++){
Thread thread =new Thread(new Runnable() {
public void run() {
System.out.println(
Thread.currentThread().getName()+"不安全值:"+SafeCountTest.unsafeCount()+"---"+
"安全值"+SafeCountTest.safeCount());
countDownLatch.countDown();
}
});
thread.start();
}
countDownLatch.await();
long endTime = System.currentTimeMillis();
System.out.println(count+"+=="+atomicInteger.get()+"总耗时:"+(endTime-startTime));
}
static int safeCount = 0;
static AtomicInteger atomicInteger = new AtomicInteger(safeCount);
public static int safeCount(){
return atomicInteger.incrementAndGet();
}
static int count = 0;
public static int unsafeCount(){
return ++count;
}
}
输出部分结果:
Thread-0不安全值:1---安全值1
Thread-1不安全值:2---安全值2
Thread-2不安全值:3---安全值3
...
...
Thread-2998不安全值:2991---安全值2998
Thread-2997不安全值:2992---安全值2999
Thread-2999不安全值:2993---安全值3000
2993+==3000总耗时:631
CAS操作就是(Compare And Swap)比较并交换。看一下示例的写法就很容易懂了。
/**
* 使用CAS实现线程安全计数器
*/
private void safeCountByCAS(){
for(;;){
int i = atomicInteger.get();//AtomicInteger 实例对象
boolean suc = atomicInteger.compareAndSet(i,++i);
if(suc){
break;
}
}
}
但是CAS实现原子操作会有三个问题:
1,ABA问题(解决办法:使用版本号解决,类似乐观锁)
2,循环时间长CUP开销大(解决办法:pause指令)
3,只能保证一个共享变量的原子操作(解决办法多个共享变量合并)