1. 程式人生 > 實用技巧 >併發程式設計中的三個問題

併發程式設計中的三個問題

併發程式設計中的三個問題

可見性

  概念:可見性(Visibility)指一個執行緒對共享變數進行修改,另一個立即得到修改後的最新值;

package juc.synchronized_test;
​
import java.util.concurrent.TimeUnit;
​
/**
 * @author : 雪飛oubai
 * @date : 2020/4/9 11:07
 * 目的:演示可見性問題
 *      1、建立一個貢獻變數
 *      2、建立一條執行緒不斷的讀取共享變數
 *      3、建立一條執行緒修改共享變數
 */
public class Test01Visibility {
    
// 多個執行緒都會訪問的資料,我們稱為執行緒的共享資料 private static boolean flag = true; public static void main(String[] args) throws InterruptedException { new Thread(() -> { while(flag){ ​ } }).start(); ​ TimeUnit.SECONDS.sleep(1); ​ new Thread(() -> { flag
= false; System.out.println("時間到,執行緒2設定為false"); }).start(); } }


原子性

  概念:原子性(Atomicity)在一次或多次操作中,要麼所有的操作都執行並且不會受其它因素影響,要麼所有的操作都不執行;

package juc.synchronized_test;
​
import java.util.ArrayList;
import java.util.List;
​
/**
 * @author : 雪飛oubai
 * @date : 2020/4/9 11:27
 * 目標:演示原子性問題
 * 1、定義一個共享變數 number
 * 2、對number進行10000次 ++ 操作
 * 3、使用 5 個執行緒來進行
 
*/ public class Test02Atomicity { //1、定義一個共享變數 number private static int number = 0; ​ public static void main(String[] args) throws InterruptedException { Runnable increment = () -> { for (int i = 0; i < 10000; i++) { number++; } }; List<Thread> list = new ArrayList<>(); ​ for (int i = 0; i < 5; i++) { Thread t = new Thread(increment); t.start(); list.add(t); } for (Thread thread : list) { thread.join(); } System.out.println("number="+number); } }

其中,對於 number ++ 而言(number為靜態變數),實際會產生如下的JVM位元組碼指令

由此可見 number++ 是由多條語句組成,以上多條指令在一個執行緒的情況下不會出現問題,但是再多執行緒情況下就可能會出現問題。比如一個執行緒在執行 13:iadd時,另一個執行緒又執行 9:getstatic,會導致兩次number++,實際上只會加一次;

小結

  併發程式設計會出現原子性問題,當一個執行緒對共享變數操作到一半時,另外的執行緒也有可能來操作共享變數,干擾了前一個執行緒的操作;

有序性

  概念:有序性(Ordering)是指程式中程式碼的執行順序,Java在編譯時和執行時會對程式碼進行優化,會導致程式最終的執行順序不一定就是我們編寫程式碼時的順序;