原子變量java
爲了引出原子變量這個概念,咱們先看一個例子。算法
1 package com.ccfdod.juc; 2 3 public class TestAtomicDemo { 4 5 public static void main(String[] args) { 6 AtomicDemo ad = new AtomicDemo(); 7 8 for (int i = 0; i < 10; i++) { 9 new Thread(ad).start(); 10 } 11 } 12 } 13 14 class AtomicDemo implements Runnable { 15 private int number = 0; 16 17 @Override 18 public void run() { 19 try { 20 Thread.sleep(200); 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 } 24 System.out.println(Thread.currentThread().getName() + " : " + getNumber()); 25 } 26 27 public int getNumber() { 28 return number++; 29 } 30 }
程序運行結果以下:安全
1 Thread-4 : 2 2 Thread-0 : 6 3 Thread-2 : 3 4 Thread-5 : 5 5 Thread-7 : 4 6 Thread-3 : 1 7 Thread-6 : 2 8 Thread-1 : 0 9 Thread-9 : 8 10 Thread-8 : 7
從程序運行結果能夠看出,Thread-4和Thread-6執行結果都爲2,明顯發生了線程安全問題,固然,這種狀況是偶然的。那麼,出現這種問題的緣由是什麼呢?併發
若是你對j = i++;底層是若是實現的,那麼這個問題就好理解了。j = i++;底層實現爲:ide
int temp = i; i = i + 1; j = temp;
那麼很明顯,Thread-4(或Thread-6)在執行改操做加1以前,Thread-6(或Thead-4)讀到了相同的值。而後都進行加1操做,再打印出來。atom
對於這類問題,咱們能夠使用原子變量來解決。在jdk1.5後,java.util.concurrent.atomic包中提供了經常使用的原子變量。原子變量有一下特性:spa
CAS算法線程
CAS算法是硬件對於併發操做共享數據的支持,CAS包含了三個操做數:code
而且,當且僅當V==A時,V=B,不然,將不作任何操做。blog
在瞭解了原子變量後,咱們使用原子變量修改程序:
1 class AtomicDemo implements Runnable { 2 // private int number = 0; 3 private AtomicInteger number = new AtomicInteger(); 4 5 @Override 6 public void run() { 7 try { 8 Thread.sleep(200); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 System.out.println(Thread.currentThread().getName() + " : " + getNumber()); 13 } 14 15 public int getNumber() { 16 // return number++; 17 return number.getAndIncrement(); 18 } 19 }