java编程规范中long与double操作并不是原子的,在java的部分执行环境中,对于long以及double的操作并不是原子的。
例如有一个long类型的longfield字段,某个线程正在执行:longfield = 123L ;这样的指定操作,而同时有另一个线程正在执行:longfield = 456L;这样的指定操作。之后longfield的值会是什么,是无法保证的。也许是123L,也可能是456L,或许是0L,甚至还可能是31415926L。
所以我们可以的出下列结论:
1.基本类型,引用类型的指定,引用是原子的操作;
2.但是long与double的指定,引用是分割的;
3.要在线程间共享long与double字段是,必须在synchronized中操作,或是声明为volatile。
以前只知道Java中的long与double不是线程安全的,但不知道为什么,读《深入java虚拟机》一书,了解了大概。
Java虚拟机规范定义的许多规则中的一条:所有对基本类型的操作,除了某些对long类型和double类型的操作之外,都必须是原子级的。
由于规范没有规定如何实现,那么当今所知的虚拟机对这条规则的实现都是把32位值做为原子性对待,而不是64位做为原子性。那么,当线程把主存中的long/double类型的值读到线程内存中时,可能是两次32位值的写操作,显而易见,如果几个线程同时操作,那么就可能会出现高低2个32位值出错的情况发生,所以现在,java程序必须确保通过同步来操作共享的long和double。
AtomicInteger:原子数字
可以对int型进行自增、自减、相加操作,保证操作的原子性。
原子类有AtomicLong、AtomicBoolean、AtomicReference等
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// 获取指针类Unsafe
private static final Unsafe unsafe = Unsafe.getUnsafe();
//下述变量value在AtomicInteger实例对象内的内存偏移量
private static final long valueOffset;
static {
try {
//通过unsafe类的objectFieldOffset()方法,获取value变量在对象内存中的偏移
//通过该偏移量valueOffset,unsafe类的内部方法可以获取到变量value对其进行取值或赋值操作
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
//当前AtomicInteger封装的int变量value
private volatile int value;
public AtomicInteger(int initialValue) {
value = initialValue;
}
public AtomicInteger() {
}
//获取当前最新值,
public final int get() {
return value;
}
//设置当前值,具备volatile效果,方法用final修饰是为了更进一步的保证线程安全。
public final void set(int newValue) {
value = newValue;
}
//最终会设置成newValue,使用该方法后可能导致其他线程在之后的一小段时间内可以获取到旧值,有点类似于延迟加载
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
//设置新值并获取旧值,底层调用的是CAS操作即unsafe.compareAndSwapInt()方法
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
//如果当前值为expect,则设置为update(当前值指的是value变量),更新成功返回true,失败返回false
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
//当前值加1返回旧值,底层CAS操作
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
//当前值减1,返回旧值,底层CAS操作
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
//当前值增加delta,返回旧值,底层CAS操作
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
//当前值加1,返回新值,底层CAS操作
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
//当前值减1,返回新值,底层CAS操作
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
//当前值增加delta,返回新值,底层CAS操作
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
}
public class AtomicIntegerTest {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(10);
int newValue = atomicInteger.incrementAndGet();
// 11
System.out.println(newValue);
boolean flag = atomicInteger.compareAndSet(10, 100);
int currentValue = atomicInteger.get();
// false 11
System.out.println(flag + "\t" + currentValue);
int newValue2 = atomicInteger.incrementAndGet();
// 12
System.out.println(newValue2);
int newValue3 = atomicInteger.decrementAndGet();
// 11
System.out.println(newValue3);
int newValue4 = atomicInteger.addAndGet(10);
// 21
System.out.println(newValue4);
}
}