成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入理解并發編程中的三個問題

開發
一個線程根據boolean類型的標記flag, while循環,另一個線程改變這個flag變量的值,另 一個線程并不會停止循環。

1.可見性

可見性(Visibility):是指一個線程對共享變量進行修改,另一個先立即得到修改后的最新值。

1.1 可見性案例演示

一個線程根據boolean類型的標記flag, while循環,另一個線程改變這個flag變量的值,另 一個線程并不會停止循環。

public class VisibilityTest {
    // 多個線程都會訪問的數據,我們稱為線程的共享數據
    // 定義一個靜態的 boolean 變量 run,初始值為 true
    private static boolean run = true; 

    public static void main(String[] args) throws InterruptedException {
        // 創建并啟動線程 t1
        Thread t1 = new Thread(() -> {
            // 在 run 變量為 true 時循環輸出消息
            while (run) {
                System.out.println(Thread.currentThread().getName() + "線程1 run = " + run);
            }
            // 循環結束后輸出最終消息
            System.out.println(Thread.currentThread().getName() + "線程1 run = " + run);
        });
        t1.start(); // 啟動線程 t1

        Thread.sleep(1000); // 主線程睡眠1秒鐘

        // 創建并啟動線程 t2
        Thread t2 = new Thread(() -> {
            run = false; // 將 run 變量設置為 false
            System.out.println(Thread.currentThread().getName() + "時間到,線程2設置為false");
        });
        t2.start(); // 啟動線程 t2
    }
}

輸出結果:

Thread-0線程1 run = true
Thread-0線程1 run = true
// .....結果省略
Thread-1時間到,線程2設置為false
Thread-0線程1 run = false

線程1開始運行時run=true,所以會不斷循環輸出Thread-0線程1 run = true,線程2運行后設置run=false,線程1發現run=true后就停止輸出。

總結:并發編程時,會出現可見性問題,當一個線程對共享變量進行了修改,另外的線程并沒有立即看到修改后的最新值。

2.原子性

原子性(Atomicity):在一次或多次操作中,要么所有的操作都執行并且不會受其他因素干擾而中斷,要么所有的操作都不執行。

2.1 可見性案例演示

5個線程各執行1000次 i++

public class AtomicityTest {
    private static int number = 0; // 定義一個靜態的整數變量 number,初始值為 0

    public static void main(String[] args) throws InterruptedException {
        Runnable increment = () -> {
            // 定義一個 Runnable 匿名類 increment,用于對 number 進行累加操作
            for (int i = 0; i < 1000; i++) {
                number++; // 對 number 進行累加操作
            }
        };

        ArrayList<Thread> ts = new ArrayList<>(); // 創建一個 ArrayList 用于存儲線程對象
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(increment); // 創建一個新線程,傳入 increment Runnable 實例
            t.start(); // 啟動線程
            ts.add(t); // 將線程對象添加到 ArrayList 中
        }

        for (Thread t : ts) {
            t.join(); // 等待所有子線程執行完畢
        }

        System.out.println("number = " + number); // 輸出最終的 number 值
    }
}

思考:最終number結果可能是多少?

結果可能是5000,也可能是小于5000的結果都有可能。

對于 number++ 而言(number 為靜態變量),實際會產生如下的 JVM 字節碼指令:

9: getstatic #12 // Field number:I
12: iconst_1
13: iadd
14: putstatic #12 // Field number:I

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

總結:并發編程時,會出現原子性問題,當一個線程對共享變量操作到一半時,另外的線程也有可能來操作共享變量,干擾了前一個線程的操作。

3.有序性

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

3.1.  有序性可見性案例演示

有序性

jcstress是Java并發壓測工具。

pom文件,添加依賴。

<dependency>
    <groupId>org.openjdk.jcstress</groupId>
    <artifactId>jcstress-core</artifactId>
    <version>0.5</version>
</dependency>

代碼:

@JCStressTest
@Outcome(id = {"1", "4"}, expect = Expect.ACCEPTABLE, desc = "ok")
@Outcome(id = "0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "danger")
@State
public class OrderingTest {

   int num = 0;
   boolean ready = false;
   // 線程1執行的代碼
    @Actor
   public void actor1(I_Result r) {
       if (ready) {
           r.r1 = num + num;
       } else {
           r.r1 = 1;
       }
   }

   // 線程2執行的代碼
    @Actor
   public void actor2(I_Result r) {
       num = 2;
       ready = true;
   }
}

I_Result 是一個對象,有一個屬性 r1 用來保存結果。

思考:在多線程情況下可能出現幾種結果?

  • 情況1:線程1先執行actor1,這時ready = false,所以進入else分支結果為1。
  • 情況2:線程2執行到actor2,執行了num = 2;和ready = true,線程1執行,這回進入 if 分支,結果為 4。
  • 情況3:線程2先執行actor2,只執行num = 2;但沒來得及執行 ready = true,線程1執行,還是進入else分支,結果為1。

注意:還有第四種情況,結果為0。

  • 情況4:線程2java編譯后結果
ready = true;
num = 2;

線程2先執行actor2,執行了ready = true,但沒來得及執行執行num = 2,線程1執行,還是進入if分支,結果為0。

運行測試:

mvn clean install
java -jar target/jcstress.jar

部分jcstress測試結果,0結果出現1384次。

完整pox.xml:

<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <javac.target>1.8</javac.target>
        <uberjar.name>jcstress</uberjar.name>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjdk.jcstress</groupId>
            <artifactId>jcstress-core</artifactId>
            <version>0.5</version>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <compilerVersion>${javac.target}</compilerVersion>
                    <source>${javac.target}</source>
                    <target>${javac.target}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.2</version>
                <executions>
                    <execution>
                        <id>main</id>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <finalName>${uberjar.name}</finalName>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>org.openjdk.jcstress.Main</mainClass>
                                </transformer>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>META-INF/TestList</resource>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>


責任編輯:華軒 來源: springboot葵花寶典
相關推薦

2020-12-11 07:32:45

編程ThreadLocalJava

2020-11-13 08:42:24

Synchronize

2022-10-12 07:53:46

并發編程同步工具

2024-12-31 09:00:12

Java線程狀態

2019-06-25 10:32:19

UDP編程通信

2023-10-27 07:47:58

Java語言順序性

2021-07-26 07:47:37

無鎖編程CPU

2020-10-20 06:45:48

編程高并發

2022-03-25 09:01:16

CSS溢出屬性

2020-07-03 07:56:34

Golang編程語言

2024-07-18 10:12:04

2023-10-27 07:47:37

計算機內存模型

2019-07-24 16:04:47

Java虛擬機并發

2018-03-22 18:30:22

數據庫MySQL并發控制

2024-05-11 07:13:33

C#Task編程

2024-06-25 08:33:48

2024-08-07 08:24:57

2010-06-28 10:12:01

PHP匿名函數

2023-10-08 08:53:36

數據庫MySQL算法

2014-06-23 10:42:56

iOS開發UIScrollVie
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 北条麻妃一区二区三区在线视频 | 国产精品夜间视频香蕉 | 成人影院av | 亚洲精久| 一级片成人 | 午夜视频网站 | 97超碰站 | 国产一区二区自拍 | 国产精品夜夜春夜夜爽久久电影 | 99精品国产一区二区三区 | 国产在线视频三区 | 日韩欧美一区二区三区免费观看 | 亚洲av毛片成人精品 | 日韩欧美亚洲 | 国产在线精品一区二区三区 | 国产精品高清在线 | 亚洲国产精品一区二区久久 | 欧美一级欧美一级在线播放 | gav成人免费播放视频 | 一区二区三区视频在线 | 久久久久久91 | 亚洲国产精品人人爽夜夜爽 | 午夜国产精品视频 | 久久久婷婷 | 日韩中文字幕av | 狠狠操电影 | a级免费黄色片 | 伊人久久成人 | 99re视频在线| 免费成人av网站 | 国产成人精品一区二区三区视频 | 国产精品毛片无码 | 久久成人免费 | 欧美激情精品久久久久 | 久久99精品久久久久久国产越南 | 欧美精品91 | 日韩电影中文字幕 | 欧美黑人一区二区三区 | 亚洲欧美激情网 | 国产1页 | 国产在线第一页 |