1、原子变量
JDK1.5后,java.util.concurrent.atomic 包下提供了一些原子操作的常用类: 类似包装类
核心方法:boolean compareAndSet(expectedValue, updateValue)
1.1 i++的原子性问题
i++的操作实际上分为三个步骤:读-改-写
int temp = i;
i = i +1;
i = temp;
public class CASTest {
public static void main(String[] args) {
AtomicTest at=new AtomicTest();
for (int i=0;i<10;i++){
new Thread(at).start();
}
}
}
class AtomicTest implements Runnable{
private int sourceNumber=0;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getSourceNumber());
}
public int getSourceNumber(){
return sourceNumber++;
}
}
结果:有重复
使用volatile也不行,因为volatile保证内存可见性,不能保证原子性问题,
使用原子变量:
public class CASTest {
public static void main(String[] args) {
AtomicTest at=new AtomicTest();
for (int i=0;i<10;i++){
new Thread(at).start();
}
}
}
class AtomicTest implements Runnable{
//private int sourceNumber=0;
private AtomicInteger sourceNumber=new AtomicInteger();
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getSourceNumber());
}
public int getSourceNumber(){
return sourceNumber.getAndIncrement();//相当于i++
}
}
运行结果:无重复
2、CAS算法
- CAS (Compare-And-Swap) 是一种硬件对并发的支持,针对多处理器操作而设计的处理器中的一种特殊指令,用于管理对共享数据的并发访问。
- CAS 是一种无锁的非阻塞算法的实现。
- CAS 包含了 3 个操作数:
需要读写的内存值 V
进行比较的值 A
拟写入的新值 B - 当且仅当 V 的值等于 A 时,CAS 通过原子方式用新值 B 来更新 V 的值,否则不会执行任何操作。
- 如以上例子就是利用CAS算法
模拟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() {
boolean b = cas.compareAndSet(cas.get(), (int) (Math.random()*101));
System.out.println(b);
}
}).start();
}
}
}
/**
* 需要读写的内存值 V
* 进行比较的值 A
* 拟写入的新值 B
*/
class CompareAndSwap{
private int V;
//获取内存值
public synchronized int get(){
return V;
}
//比较
public synchronized int compareAndSwap(int A,int B){
int oldV= V;
if (oldV == A){
this.V = B;
}
return oldV;
}
//设置
public synchronized boolean compareAndSet(int A,int B){
return A == compareAndSwap(A,B);
}
}