为什么会有并发问题
- 并发程序的关键在于对共享的,可变的状态进行访问管理
- 不可变对象永远是线程安全的
- 因此,即使多个线程之间没有使用同步,也不保证一定会发生内存可见性问题(指线程读取到过期的值),java内存模型仅仅是允许内存可见性问题发生而已。在很多当前的JVM实现和java执行平台中,甚至是在那些使用多处理器的JVM和平台中,也很少出现内存可见性问题。
- 这使得测试基于内存可见性的错误是不切实际的,因为这样的错误极难发生。
- 如果把一个字段声明为volatile型,线程对这个字段写入后,在执行后续的内存访问之前,线程必须刷新这个字段且让这个字段对其他线程可见(即该字段立即刷新)。每次对volatile字段的读访问,都要重新装载字段的值。
为什么volatile要和compareAndSet配合起来使用?
public final long getAndIncrement() {
while (true) {
long current = get();
long next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
- 如果long current = get()中get()的值不是volatile的话,有可能会导致死循环
- 因为只有是volatile的变量才满足下面两点,这两点对于cas操作非常重要
- 在读之前需要强制更新成主内存中的数据
- 在写之后需要强制更新到主内存中的数据
- 所以在getAndIncrement操作中cas保证原子性,volatile保证内存可见性,两者共同完成无锁的原子操作
使用AtomicXXX的两个重要原因
- 性能好很多
- 使用方便
可以参见: http://stackoverflow.com/questions/11670687/when-is-atomicinteger-preferrable-over-synchronized