原子性
原子是世界上的最小機關,具有不可分割性。比如 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
2. /**
3. * 可見性分析
4. * @author Administrator
5. *
6. *volatile 會拒絕編譯器對其修飾的變量進行優化。也就不會存在重排序的問題。volatile隻會影響可見性,不會影響原子性。
7. *下面程式如果不加
8. */
9. public class
10.
11. volatile int a = 1;
12. volatile boolean
13.
14. public class PrintA extends
15. @Override
16. public void
17. while(!ready){
18. Thread.yield();
19. }
20. System.out.println(a);
21. }
22. }
23. public static void main(String[] args) throws
24. new
25. new
26. //下面兩行如果不加volatile的話,執行的先後順序是不可預測的。并且下面兩行都是原子操作,但是這兩行作為一個整體的話就不是一個原子操作。
27. 48; //這是一個原子操作,但是其結果不一定具有可見性。加上volatile後就具備了可見性。
28. true;//同理
29. }
30.
31. }
package com.chu.test.thread;
/**
* 可見性分析
* @author Administrator
*
*volatile 會拒絕編譯器對其修飾的變量進行優化。也就不會存在重排序的問題。volatile隻會影響可見性,不會影響原子性。
*下面程式如果不加
*/
public class Test {
volatile int a = 1;
volatile boolean ready;
public class PrintA extends Thread{
@Override
public void run() {
while(!ready){
Thread.yield();
}
System.out.println(a);
}
}
public static void main(String[] args) throws InterruptedException {
Test t = new Test();
t.new PrintA().start();
//下面兩行如果不加volatile的話,執行的先後順序是不可預測的。并且下面兩行都是原子操作,但是這兩行作為一個整體的話就不是一個原子操作。
t.a = 48; //這是一個原子操作,但是其結果不一定具有可見性。加上volatile後就具備了可見性。
t.ready = true;//同理
}
}
上面程式如果變量a不用volatile修飾那麼輸出結果很可能就是0.。
原子性
原子是世界上的最小機關,具有不可分割性。比如 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
2. /**
3. * 可見性分析
4. * @author Administrator
5. *
6. *volatile 會拒絕編譯器對其修飾的變量進行優化。也就不會存在重排序的問題。volatile隻會影響可見性,不會影響原子性。
7. *下面程式如果不加
8. */
9. public class
10.
11. volatile int a = 1;
12. volatile boolean
13.
14. public class PrintA extends
15. @Override
16. public void
17. while(!ready){
18. Thread.yield();
19. }
20. System.out.println(a);
21. }
22. }
23. public static void main(String[] args) throws
24. new
25. new
26. //下面兩行如果不加volatile的話,執行的先後順序是不可預測的。并且下面兩行都是原子操作,但是這兩行作為一個整體的話就不是一個原子操作。
27. 48; //這是一個原子操作,但是其結果不一定具有可見性。加上volatile後就具備了可見性。
28. true;//同理
29. }
30.
31. }
package com.chu.test.thread;
/**
* 可見性分析
* @author Administrator
*
*volatile 會拒絕編譯器對其修飾的變量進行優化。也就不會存在重排序的問題。volatile隻會影響可見性,不會影響原子性。
*下面程式如果不加
*/
public class Test {
volatile int a = 1;
volatile boolean ready;
public class PrintA extends Thread{
@Override
public void run() {
while(!ready){
Thread.yield();
}
System.out.println(a);
}
}
public static void main(String[] args) throws InterruptedException {
Test t = new Test();
t.new PrintA().start();
//下面兩行如果不加volatile的話,執行的先後順序是不可預測的。并且下面兩行都是原子操作,但是這兩行作為一個整體的話就不是一個原子操作。
t.a = 48; //這是一個原子操作,但是其結果不一定具有可見性。加上volatile後就具備了可見性。
t.ready = true;//同理
}
}