JAVA 中无锁的线程安全整数 AtomicInteger,一个提供原子操做的Integer的类。在Java语言中,++i和i++操做并非线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则经过一种线程安全的加减操做接口。AtomicInteger为何可以达到多而不乱,处理高并发应付自如呢?这是由硬件提供原子操做指令实现的,这里面用到了一种并发技术:CAS。在非激烈竞争的状况下,开销更小,速度更快。
Java.util.concurrent中实现的原子操做类包括:java
AtomicBoolean、AtomicInteger、AtomicIntegerArray、AtomicLong、AtomicReference、AtomicReferenceArray。
1.悲观锁与乐观锁:程序员
- 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,因此每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了不少这种锁机制,好比行锁,表锁等,读锁,写锁等,都是在作操做以前先上锁。 - 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,因此不会上锁,可是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可使用版本号等机制。乐观锁适用于多读的应用类型,这样能够提升吞吐量,像数据库若是提供相似于write_condition机制的其实都是提供的乐观锁。
两种锁各有优缺点,不可认为一种好于另外一种,像乐观锁适用于写比较少的状况下,即冲突真的不多发生的时候,这样能够省去了锁的开销,加大了系统的整个吞吐量。但若是常常产生冲突,上层应用会不断的进行retry,这样反却是下降了性能,因此这种状况下用悲观锁就比较合适。数据库
2.CAS:安全
CAS就是Compare and Swap的意思,比较并操做。不少的cpu直接支持CAS指令。CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知此次竞争中失败,并能够再次尝试。CAS有3个操做数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改成B,不然什么都不作。多线程
private static final Unsafe unsafe = Unsafe.getUnsafe();
package AtomicData; import java.util.concurrent.atomic.AtomicInteger; public class Test { public static void main(String[] args) throws InterruptedException { Test test = new Test(); MyThread my = new MyThread(test); for (int i = 0; i < 500; i++) { Thread t = new Thread(my); t.start(); } //等待子线程执行完 Thread.sleep(5000); System.out.println(test.number); } AtomicInteger number = new AtomicInteger(0); protected void update() { number.getAndAdd(1); } } class MyThread implements Runnable { Test t; public MyThread(Test t){ this.t =t; } @Override public void run() { t.update(); } }