1、简介
Atomic一词跟原子有点关系,后者曾被人认为是最小物质的单位。计算机中的Atomic是指不能分割成若干部分的意思。如果一段代码被认为是Atomic,则表示这段代码在执行过程中,是不能被中断的。通常来说,原子指令由硬件提供,供软件来实现原子方法(某个线程进入该方法后,就不会被中断,直到其执行完成)
在x86 平台上,CPU提供了在指令执行期间对总线加锁的手段。CPU芯片上有一条引线#HLOCK pin,如果汇编语言的程序中在一条指令前面加上前缀”LOCK”,经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。
原子变量的原子操作也是用到了锁,只不过这个是硬件指令级别的锁,比我们软件实现的锁高效很多,更重要的是如果出现了冲突,只是不停的循环重试,而不会切换线程。如:do{ }while 循环调用一个本地方法。
2、java提供的原子类
- 原子更新基本类型
- 原子更新数组
- 原子更新抽象类型
- 原子更新字段
3、原子类的使用
public class Sequence {
// 原子性的Integer类 可以进行原子操作
private AtomicInteger value = new AtomicInteger(0);
private int [] i = {2,1,4,6};
// 原子性的Integer数组 可以进行原子操作
private AtomicIntegerArray a = new AtomicIntegerArray(i);
// 对普通类进行原子性引用 可以进行原子操作
//对user的get和set方法进行原子操作,而不是对其属性
private AtomicReference<User> user = new AtomicReference<>();
// 对普通类的属性修改 可以进行原子操作 属性必须得用volatile修饰 public volatile int old;
private AtomicIntegerFieldUpdater<User> old = AtomicIntegerFieldUpdater.newUpdater(User.class, "old");
/**
* 原子操作 不会再出现线程安全问题
*/
public int getNext() {
//return value.getAndAdd(10);//value每次加10
//return value.getAndIncrement();//value++
//a.getAndIncrement(2);//给第2个位置的值加1
//a.getAndAdd(2, 5);//给第2个位置的值加10
User u = new User();
System.out.println(old.getAndIncrement(u));
System.out.println(old.getAndIncrement(u));
System.out.println(old.getAndIncrement(u));
return a.get(2);
}
public static void main(String[] args) {
Sequence sequence = new Sequence();
//第一个线程
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()+" ----->"+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//第二个线程
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()+" ----->"+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//第三个线程
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName()+" ----->"+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
4、原理
//用其中一个方法讲解
public class AtomicInteger extends Number implements java.io.Serializable {
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();//拿到当前的值
next = updateFunction.applyAsInt(prev);//计算下一个值
} while (!compareAndSet(prev, next));//compareAndSet 如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。这里需要注意的是这个方法的返回值实际上是是否成功修改,而与之前的值无关。
return next;
}