版权声明:版权所有,翻版我也没办法!!! https://blog.csdn.net/tebtebtebteb/article/details/82964699
引入:
我们都知道i++在java中不是原子操作,因为i++的操作实际上分为三个步骤“读-改-写”,
int i =10;
i = i++;
实际上是分为下面几步:
int temp = i;
i = i + 1;
i = temp;
反编译后可以看到每条指令都会产生一个get和put,它们之间还有一些其他的指令。因此在获取和放置之间,另一个任务可能会修改这个域,所以这些操作不是原子性的。
JavaSE5引入了诸如AtomicInteger、AtomicLong、AtomicReference等特殊的原子性变量类,可以实现原子操作。它们提供下面形式的原子性条件更新操作:
boolean compareAndSet(expectedValue,updateValue);
这个被称作CAS(Compare-And-Swap) :比较并交换,该算法是硬件对于并发操作的支持。
CAS包含了三个操作数:
①内存值 V
②预估值 A
③更新值 B
当前仅当V == A时,V = B,否则不会执行任何操作。
模拟CAS算法:
package com.tongtong.app5;
/**
*模拟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() {
int expectedValue = cas.get();
boolean b = cas.compareAndSet(expectedValue,(int)(Math.random()*101));
System.out.println(b);
}
}).start();
}
}
}
class CompareAndSwap{
private int value;
//获取内存值
public synchronized int get(){
return value;
}
//比较
public synchronized int compareAndSwap(int expectValue,int newValue){
int oldValue = value;
if(oldValue == expectValue){
this.value = newValue;
}
return oldValue;
}
//设置
public synchronized boolean compareAndSet(int expectValue,int newValue){
return expectValue == compareAndSwap(expectValue,newValue);
}
}
原子类操作:
package com.tongtong.app6;
import java.util.concurrent.atomic.AtomicInteger;
public class TestAtomicDemo {
public static void main(String[] args) {
AtomicDemo ad = new AtomicDemo();
for(int i = 0;i < 10; i++){
new Thread(ad).start();
}
}
}
class AtomicDemo implements Runnable{
private AtomicInteger serialNumber = new AtomicInteger(0);
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getSerialNumber());
}
public int getSerialNumber(){
return serialNumber.getAndIncrement(); //加1,相当于i++
}
}
若想更多的了解原子操作,可以进入以下链接进行学习: