步骤 1 : 原子性操做概念html
所谓的原子性操做即不可中断的操做,好比赋值操做java
int i = 5;
原子性操做自己是线程安全的 可是 i++ 这个行为,事实上是有3个原子性操做组成的。安全
步骤 1. 取 i 的值 步骤 2. i + 1 步骤 3. 把新的值赋予i
这三个步骤,每一步都是一个原子操做,可是合在一块儿,就不是原子操做。就不是线程安全的。 换句话说,一个线程在步骤1 取i 的值结束后,尚未来得及进行步骤2,另外一个线程也能够取 i的值了。 这也是分析同步问题产生的缘由 中的原理。 i++ ,i--, i = i+1 这些都是非原子性操做。 只有int i = 1,这个赋值操做是原子性的。多线程
步骤 2 : AtomicInteger测试
JDK6 之后,新增长了一个包java.util.concurrent.atomic,里面有各类原子类,好比AtomicInteger。 而AtomicInteger提供了各类自增,自减等方法,这些方法都是原子性的。 换句话说,自增方法 incrementAndGet 是线程安全的,同一个时间,只有一个线程能够调用这个方法。atom
package multiplethread; import java.util.concurrent.atomic.AtomicInteger; public class TestThread { public static void main(String[] args) throws InterruptedException { AtomicInteger atomicI =new AtomicInteger(); int i = atomicI.decrementAndGet(); int j = atomicI.incrementAndGet(); int k = atomicI.addAndGet(3); } }
步骤 3 : 同步测试spa
分别使用基本变量的非原子性的**++运算符和 原子性的AtomicInteger对象的 incrementAndGet** 来进行多线程测试。 测试结果如图所示线程
package multiplethread; import java.util.concurrent.atomic.AtomicInteger; public class TestThread { private static int value = 0; private static AtomicInteger atomicValue =new AtomicInteger(); public static void main(String[] args) { int number = 100000; Thread[] ts1 = new Thread[number]; for (int i = 0; i < number; i++) { Thread t =new Thread(){ public void run(){ value++; } }; t.start(); ts1[i] = t; } //等待这些线程所有结束 for (Thread t : ts1) { try { t.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.printf("%d个线程进行value++后,value的值变成:%d%n", number,value); Thread[] ts2 = new Thread[number]; for (int i = 0; i < number; i++) { Thread t =new Thread(){ public void run(){ atomicValue.incrementAndGet(); } }; t.start(); ts2[i] = t; } //等待这些线程所有结束 for (Thread t : ts2) { try { t.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.printf("%d个线程进行atomicValue.incrementAndGet();后,atomicValue的值变成:%d%n", number,atomicValue.intValue()); } }
更多内容,点击了解: 多线程 原子访问3d