AtomicIntege解决以下三个问题
- 可见性
- 有序性
- 原子性
compareAndSet使用的是cpu级别的加锁
volatile只能保证可见性和有序性,但是不能保证原子性,代码如下:
public class AtomicIntegerTest {
private volatile static int value = 1;
private static Set<Integer> set = Collections.synchronizedSet(new HashSet<>());
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread() {
@Override
public void run() {
int x = 1;
while (x <= 50000) {
set.add(value);
int tmp = value;
System.out.println(Thread.currentThread().getName() + ":" + tmp);
value += 1;
x++;
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
int x = 1;
while (x <= 50000) {
set.add(value);
int tmp = value;
System.out.println(Thread.currentThread().getName() + ":" + tmp);
value += 1;
x++;
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(set.size());
}
}
应该是10000
AtomicInteger可以保证原子性,可见性和有序性(private volatile int value;)
public class AtomicIntegerTest {
private volatile static int value;
private static Set<Integer> set = Collections.synchronizedSet(new HashSet<>());
public static void main(String[] args) throws InterruptedException{
AtomicInteger atomicInteger = new AtomicInteger(1);
Thread t1 = new Thread() {
@Override
public void run() {
int x = 1;
while (x <= 50000) {
int v = atomicInteger.getAndIncrement();
set.add(v);
System.out.println(Thread.currentThread().getName() + ":" + v);
x++;
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
int x = 1;
while (x <= 50000) {
int v = atomicInteger.getAndIncrement();
set.add(v);
System.out.println(Thread.currentThread().getName() + ":" + v);
x++;
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(set.size());
}
}
利用compareAndSet的特性来实现一个显示的锁,不同于synchronized的是,当没有抢到锁的线程会立即失败,而不是blocked住
package com.picc.concerrent3.chapter1;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 通过compareAndSet的特性实现一个锁
*/
public class CompareAndSetLock {
private final AtomicInteger value = new AtomicInteger(0);
private Thread lockThread;
public void tryLock() throws GetLockException{
boolean success = value.compareAndSet(0, 1);
if(!success){
throw new GetLockException("get the lock failed");
} else {
lockThread = Thread.currentThread();
}
}
public void unlock(){
if (0==value.get()) {
return;
}
if (lockThread == Thread.currentThread())
value.compareAndSet(1, 0);
}
}
package com.picc.concerrent3.chapter1;
public class AtomicIntegerDetailTest2 {
private final static CompareAndSetLock lock = new CompareAndSetLock();
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread(){
@Override
public void run() {
try {
// doSomething();
doSomething2();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
}
private static void doSomething() throws InterruptedException{
synchronized (AtomicIntegerDetailTest2.class){
System.out.println(Thread.currentThread().getName()+" get the lock");
Thread.sleep(100000);
}
}
private static void doSomething2() throws Exception{
try{
lock.tryLock();
System.out.println(Thread.currentThread().getName()+" get the lock");
Thread.sleep(100000);
}finally {
lock.unlock();
}
}
}
AtomicInteger类源码
private volatile int value;
static {
try {
// 获取value对应的值在内存中的偏移量
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 原子自增
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
Unsafe类源码
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
// 首先获取value对应的内存中的值
var5 = this.getIntVolatile(var1, var2);
// var5 是预期值 var5 + var4是待更新值
// var1(当前对象)和var2(代表偏移量)可以确定一个内存中的值,和var5预期值进行比较,如果一直,就更新为待更新值,退出自旋,如果不一致,重新获取内存中的值
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}