java併發之原子性與可見性

java併發之原子性與可見性(一)java

原子性

原子是世界上的最小單位,具備不可分割性。好比 a=0;(a非long和double類型) 這個操做是不可分割的,那麼咱們說這個操做時原子操做。再好比:a++; 這個操做實際是a = a + 1;是可分割的,因此他不是一個原子操做。非原子操做都會存在線程安全問題,須要咱們使用同步技術(sychronized)來讓它變成一個原子操做。一個操做是原子操做,那麼咱們稱它具備原子性。java的concurrent包下提供了一些原子類,咱們能夠經過閱讀API來了解這些原子類的用法。好比:AtomicInteger、AtomicLong、AtomicReference等。緩存

可見性

可見性,是指線程之間的可見性,一個線程修改的狀態對另外一個線程是可見的。也就是一個線程修改的結果。另外一個線程立刻就能看到。好比:用volatile修飾的變量,就會具備可見性。volatile修飾的變量不容許線程內部緩存和重排序,即直接修改內存。因此對其餘線程是可見的。可是這裏須要注意一個問題,volatile只能讓被他修飾內容具備可見性,但不能保證它具備原子性。好比 volatile int a = 0;以後有一個操做 a++;這個變量a具備可見性,可是a++ 依然是一個非原子操做,也就這這個操做一樣存在線程安全問題。安全

他們之間關係

原子性是說一個操做是否可分割。可見性是說操做結果其餘線程是否可見。這麼看來他們其實沒有什麼關係併發

實例
  1. package com.chu.test.thread;  ide

  2. /** 優化

  3.  * 可見性分析 spa

  4.  * @author Administrator 線程

  5.  * orm

  6.  *volatile 會拒絕編譯器對其修飾的變量進行優化。也就不會存在重排序的問題。volatile只會影響可見性,不會影響原子性。 排序

  7.  *下面程序若是不加 

  8.  */  

  9. public class Test {  

  10.   

  11.     volatile int a = 1;  

  12.     volatile boolean ready;  

  13.       

  14.     public class PrintA extends Thread{  

  15.         @Override  

  16.         public void run() {  

  17.             while(!ready){  

  18.                 Thread.yield();  

  19.             }  

  20.             System.out.println(a);  

  21.         }  

  22.     }  

  23.     public static void main(String[] args) throws InterruptedException {  

  24.         Test t = new Test();  

  25.         t.new PrintA().start();  

  26.         //下面兩行若是不加volatile的話,執行的前後順序是不可預測的。而且下面兩行都是原子操做,可是這兩行做爲一個總體的話就不是一個原子操做。  

  27.         t.a = 48; //這是一個原子操做,可是其結果不必定具備可見性。加上volatile後就具有了可見性。  

  28.         t.ready = true;//同理  

  29.     }  

  30.   

  31. }  

上面程序若是變量a不用volatile修飾那麼輸出結果極可能就是0.。

相關文章
相關標籤/搜索