java.util.concurrent 是基于Queue 的并发包,而Queue,不少
状况下使用到了Atomic 操做。一般状况下,在Java里面在没有额外资源能够利用的状况下,只能使用加锁才能保证读-改-写这三个操做时“原子”的。则须要使用synchronized和volatile关键字,代价很高,还须要jni。java
JDK 5.0后,则重复使用现代cpu特性下降锁消耗算法
int addAndGet(int delta) //以原子方式将给定值与当前值相加。实际上就是等于线程安全版本的i=i+delta操做。 boolean compareAndSet(int expect, int update)//若是当前值== 预期值,则以原子方式将该值设置为给定的更新值。若是成功就返回true,不然返回false,而且不修改原值。 int decrementAndGet()//以原子方式将当前值减1。至关于线程安全版本的--i 操做。 int get()//获取当前值。 int getAndAdd(int delta)//以原子方式将给定值与当前值相加。至关于线程安全版本的t=i;i+=delta;return t;操做。 int getAndDecrement()以原子方式将当前值减1。至关于线程安全版本的i--操做。 int getAndIncrement()//以原子方式将当前值加1。至关于线程安全版本的i++操做。 int getAndSet(int newValue)//以原子方式设置为给定值, 并返回旧值。至关于线程安全版本的t=i;i=newValue;return t;操做。 int incrementAndGet()//以原子方式将当前值加1。至关于线程安全版本的++i 操做。 ...
AtomicInteger 和AtomicLong、AtomicBoolean、AtomicReference 差很少api
API和AtomicInteger 是相似的,这种经过方法、参数的名称就可以获得函数意义的写法是很是值得称赞数组
int get(int i)//获取位置i 的当前值。很显然, 因为这个是数组操做, 就有索引越界的问题 void set(int i, int newValue) void lazySet(int i, int newValue) int getAndSet(int i, int newValue) boolean compareAndSet(int i, int expect, int update) boolean weakCompareAndSet(int i, int expect, int update) int getAndIncrement(int i) int getAndDecrement(int i) int getAndAdd(int i, int delta) int incrementAndGet(int i) int decrementAndGet(int i) int addAndGet(int i, int delta)
AtomicIntegerFieldUpdater
约束:安全
只能是实例变量多线程
public class AtomicIntegerFieldUpdaterDemo { class DemoData{ public volatile int value1 = 1; } void main() { DemoData data = new DemoData(); AtomicIntegerFieldUpdater.newUpdater(DemoData.class, value1).getAndSet(data, 10)); } }
Java 语言规范规定了JVM 线程内部维持顺序化语义,也就是说只要程序的最终结果等同于
它在严格的顺序化环境下的结果,那么指令的执行顺序就可能与代码的顺序不一致。这个
过程经过叫作指令的重排序。并发
意义: JVM 可以根据处理器的特性(CPU 的多级缓存系统、多核处理器等)适当的从新排序机器指令,使机器指令更符合CPU 的执行特色,最大限度的发挥机器的性能。app
若是动做B 要看到动做A 的执行结果(不管A/B 是否在同一个线程里面执行),那么A/B 就须要知足happens-before 关系。函数
JMM 动做(Java Memeory Model Action),
Java 存储模型动做。一个动做(Action)包括:变量的读写、监视器加锁和释放锁、线程的
start()和join()
volatile 至关于synchronized 的弱实现,也就是说volatile 实现了相似synchronized 的语义,
却又没有锁机制。
尽管volatile 变量的特性不错,可是volatile 并不能保证线程安全的,也就是说volatile 字段
的操做不是原子性的,volatile 变量只能保证可见性(一个线程修改后其它线程可以理解看
到此变化后的结果),要想保证原子性,目前为止只能加锁!
缺点:
若是一个优先级高的线程等待一个优先级低的线程释放锁会致使优先级倒置,引发性能风险。
volatile 是不错的机制,可是volatile 不能保证原子性。所以对于同步最终仍是要回到锁机制
上来。
独占锁是一种悲观锁,synchronized 就是一种独占锁,会致使其它全部须要锁的线程挂起,
等待持有锁的线程释放锁。而另外一个更加有效的锁就是乐观锁。所谓乐观锁就是,每次不加
锁而是假设没有冲突而去完成某项操做,若是由于冲突失败就重试,直到成功为止。
上面的乐观锁用到的机制就是CAS,Compare and Swap。
CAS 有3个操做数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A 和内存
值V 相同时,将内存值V 修改成B,不然什么都不作。
非阻塞算法(nonblocking algorithms)
一个线程的失败或者挂起不该该影响其余线程的失败或挂起的算法。
public final int incrementAndGet() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return next; } }
总体的过程,利用CPU 的CAS 指令,同时借助JNI 来完成Java 的非阻塞算法。