日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

深入理解并發(fā)編程中的三個(gè)問題

來源: 責(zé)編: 時(shí)間:2024-03-19 17:35:13 192觀看
導(dǎo)讀1.可見性可見性(Visibility):是指一個(gè)線程對(duì)共享變量進(jìn)行修改,另一個(gè)先立即得到修改后的最新值。1.1 可見性案例演示一個(gè)線程根據(jù)boolean類型的標(biāo)記flag, while循環(huán),另一個(gè)線程改變這個(gè)flag變量的值,另 一個(gè)線程并不會(huì)停止循

1.可見性

可見性(Visibility):是指一個(gè)線程對(duì)共享變量進(jìn)行修改,另一個(gè)先立即得到修改后的最新值。ece28資訊網(wǎng)——每日最新資訊28at.com

1.1 可見性案例演示

一個(gè)線程根據(jù)boolean類型的標(biāo)記flag, while循環(huán),另一個(gè)線程改變這個(gè)flag變量的值,另 一個(gè)線程并不會(huì)停止循環(huán)。ece28資訊網(wǎng)——每日最新資訊28at.com

public class VisibilityTest {    // 多個(gè)線程都會(huì)訪問的數(shù)據(jù),我們稱為線程的共享數(shù)據(jù)    // 定義一個(gè)靜態(tài)的 boolean 變量 run,初始值為 true    private static boolean run = true;     public static void main(String[] args) throws InterruptedException {        // 創(chuàng)建并啟動(dòng)線程 t1        Thread t1 = new Thread(() -> {            // 在 run 變量為 true 時(shí)循環(huán)輸出消息            while (run) {                System.out.println(Thread.currentThread().getName() + "線程1 run = " + run);            }            // 循環(huán)結(jié)束后輸出最終消息            System.out.println(Thread.currentThread().getName() + "線程1 run = " + run);        });        t1.start(); // 啟動(dòng)線程 t1        Thread.sleep(1000); // 主線程睡眠1秒鐘        // 創(chuàng)建并啟動(dòng)線程 t2        Thread t2 = new Thread(() -> {            run = false; // 將 run 變量設(shè)置為 false            System.out.println(Thread.currentThread().getName() + "時(shí)間到,線程2設(shè)置為false");        });        t2.start(); // 啟動(dòng)線程 t2    }}

輸出結(jié)果:ece28資訊網(wǎng)——每日最新資訊28at.com

Thread-0線程1 run = trueThread-0線程1 run = true// .....結(jié)果省略Thread-1時(shí)間到,線程2設(shè)置為falseThread-0線程1 run = false

線程1開始運(yùn)行時(shí)run=true,所以會(huì)不斷循環(huán)輸出Thread-0線程1 run = true,線程2運(yùn)行后設(shè)置run=false,線程1發(fā)現(xiàn)run=true后就停止輸出。ece28資訊網(wǎng)——每日最新資訊28at.com

總結(jié):并發(fā)編程時(shí),會(huì)出現(xiàn)可見性問題,當(dāng)一個(gè)線程對(duì)共享變量進(jìn)行了修改,另外的線程并沒有立即看到修改后的最新值。ece28資訊網(wǎng)——每日最新資訊28at.com

2.原子性

原子性(Atomicity):在一次或多次操作中,要么所有的操作都執(zhí)行并且不會(huì)受其他因素干擾而中斷,要么所有的操作都不執(zhí)行。ece28資訊網(wǎng)——每日最新資訊28at.com

2.1 可見性案例演示

5個(gè)線程各執(zhí)行1000次 i++ece28資訊網(wǎng)——每日最新資訊28at.com

public class AtomicityTest {    private static int number = 0; // 定義一個(gè)靜態(tài)的整數(shù)變量 number,初始值為 0    public static void main(String[] args) throws InterruptedException {        Runnable increment = () -> {            // 定義一個(gè) Runnable 匿名類 increment,用于對(duì) number 進(jìn)行累加操作            for (int i = 0; i < 1000; i++) {                number++; // 對(duì) number 進(jìn)行累加操作            }        };        ArrayList<Thread> ts = new ArrayList<>(); // 創(chuàng)建一個(gè) ArrayList 用于存儲(chǔ)線程對(duì)象        for (int i = 0; i < 5; i++) {            Thread t = new Thread(increment); // 創(chuàng)建一個(gè)新線程,傳入 increment Runnable 實(shí)例            t.start(); // 啟動(dòng)線程            ts.add(t); // 將線程對(duì)象添加到 ArrayList 中        }        for (Thread t : ts) {            t.join(); // 等待所有子線程執(zhí)行完畢        }        System.out.println("number = " + number); // 輸出最終的 number 值    }}

思考:最終number結(jié)果可能是多少?ece28資訊網(wǎng)——每日最新資訊28at.com

結(jié)果可能是5000,也可能是小于5000的結(jié)果都有可能。ece28資訊網(wǎng)——每日最新資訊28at.com

對(duì)于 number++ 而言(number 為靜態(tài)變量),實(shí)際會(huì)產(chǎn)生如下的 JVM 字節(jié)碼指令:ece28資訊網(wǎng)——每日最新資訊28at.com

9: getstatic #12 // Field number:I12: iconst_113: iadd14: putstatic #12 // Field number:I

可見number++是由多條語句組成,以上多條指令在一個(gè)線程的情況下是不會(huì)出問題的,但是在多線程情況下就可能會(huì)出現(xiàn)問題。比如一個(gè)線程在執(zhí)行13: iadd時(shí),另一個(gè)線程又執(zhí)行9: getstatic。會(huì)導(dǎo)致兩次number++,實(shí)際上只加了1。ece28資訊網(wǎng)——每日最新資訊28at.com

總結(jié):并發(fā)編程時(shí),會(huì)出現(xiàn)原子性問題,當(dāng)一個(gè)線程對(duì)共享變量操作到一半時(shí),另外的線程也有可能來操作共享變量,干擾了前一個(gè)線程的操作。ece28資訊網(wǎng)——每日最新資訊28at.com

3.有序性

有序性(Ordering):是指程序中代碼的執(zhí)行順序,Java在編譯時(shí)和運(yùn)行時(shí)會(huì)對(duì)代碼進(jìn)行優(yōu)化,會(huì)導(dǎo)致程序最終的執(zhí)行順序不一定就是我們編寫代碼時(shí)的順序。ece28資訊網(wǎng)——每日最新資訊28at.com

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

有序性ece28資訊網(wǎng)——每日最新資訊28at.com

jcstress是Java并發(fā)壓測(cè)工具。ece28資訊網(wǎng)——每日最新資訊28at.com

pom文件,添加依賴。ece28資訊網(wǎng)——每日最新資訊28at.com

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

代碼:ece28資訊網(wǎng)——每日最新資訊28at.com

@JCStressTest@Outcome(id = {"1", "4"}, expect = Expect.ACCEPTABLE, desc = "ok")@Outcome(id = "0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "danger")@Statepublic class OrderingTest {   int num = 0;   boolean ready = false;   // 線程1執(zhí)行的代碼    @Actor   public void actor1(I_Result r) {       if (ready) {           r.r1 = num + num;       } else {           r.r1 = 1;       }   }   // 線程2執(zhí)行的代碼    @Actor   public void actor2(I_Result r) {       num = 2;       ready = true;   }}

I_Result 是一個(gè)對(duì)象,有一個(gè)屬性 r1 用來保存結(jié)果。ece28資訊網(wǎng)——每日最新資訊28at.com

思考:在多線程情況下可能出現(xiàn)幾種結(jié)果?ece28資訊網(wǎng)——每日最新資訊28at.com

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

注意:還有第四種情況,結(jié)果為0。ece28資訊網(wǎng)——每日最新資訊28at.com

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

線程2先執(zhí)行actor2,執(zhí)行了ready = true,但沒來得及執(zhí)行執(zhí)行num = 2,線程1執(zhí)行,還是進(jìn)入if分支,結(jié)果為0。ece28資訊網(wǎng)——每日最新資訊28at.com

ece28資訊網(wǎng)——每日最新資訊28at.com

運(yùn)行測(cè)試:ece28資訊網(wǎng)——每日最新資訊28at.com

mvn clean installjava -jar target/jcstress.jar

部分jcstress測(cè)試結(jié)果,0結(jié)果出現(xiàn)1384次。ece28資訊網(wǎng)——每日最新資訊28at.com

ece28資訊網(wǎng)——每日最新資訊28at.com

完整pox.xml:ece28資訊網(wǎng)——每日最新資訊28at.com

<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>


ece28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-77831-0.html深入理解并發(fā)編程中的三個(gè)問題

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 在 Go 中如何停止程序

下一篇: 構(gòu)建一個(gè)通用靈活的JavaScript插件系統(tǒng)?看完你也會(huì)!

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 临猗县| 布尔津县| 沂源县| 洛隆县| 阿城市| 江口县| 波密县| 甘德县| 商洛市| 綦江县| 龙口市| 剑川县| 色达县| 凤山县| 咸宁市| 南汇区| 太仓市| 衡水市| 孟州市| 海淀区| 保康县| 太保市| 靖宇县| 甘孜县| 达日县| 大厂| 冕宁县| 凌云县| 新津县| 合山市| 霍邱县| 荆门市| 和林格尔县| 青川县| 夏邑县| 梅河口市| 和平区| 石河子市| 荃湾区| 施甸县| 会泽县|