Java 并發(fā)編程】線程指令重排序問題 ( 指令重排序規(guī)范 | volatile 關(guān)鍵字禁止指令重排序 )

      網(wǎng)友投稿 748 2022-05-30

      文章目錄

      總結(jié)

      一、指令重排序規(guī)范

      二、指令重排序示例

      總結(jié)

      Java 并發(fā)的 3 3 3 特性 :

      原子性 : 每個操作都是

      不可拆分的原子操作

      ; 在線程中進行 a++ 就不是原子操作 , 該操作分為 3 3 3 個步驟 , 首先從主內(nèi)存中讀取 a 變量 , 然后進行自增操作 , 最后在將自增后的值寫回主內(nèi)存中 ;

      可見性 :

      多個線程

      訪問同一個變量 , 該變量一旦被

      某個線程修改

      , 這些線程必須可以

      立刻看到被修改的值 ;

      有序性 : 程序按照

      代碼先后順序

      執(zhí)行 ;

      使用 volatile 關(guān)鍵字只能保證 可見性 和 有序性 , 但是不能保證原子性 ;

      volatile 可以激活線程共享變量的 "

      緩存一致性協(xié)議

      " ; 保證

      可見性 ;

      volatile 可以 禁止 JVM 的 "

      指令重排

      " ; 保證

      有序性 ;

      一、指令重排序規(guī)范

      指令重排指的是 , 線程中如果兩行代碼

      沒有邏輯上的上下關(guān)系

      , 可以對代碼進行

      重新排序 ;

      JVM 指令重排遵循規(guī)范 :

      as-if-serial 規(guī)范 : 單個線程中, 指令的重排 ,

      不能影響程序的執(zhí)行結(jié)果 ;

      可以重排的情況 : 對于下面代碼 ,

      兩條指令順序顛倒 , 執(zhí)行結(jié)果相同 ,

      可以進行指令重排 ;

      x = 0; y = 1;

      1

      2

      不可以進行重排的情況 : 對于下面的代碼 ,

      兩條指令如果上下顛倒 , 結(jié)果不同 ,

      不可以進行指令重排 ;

      x = 0; y = x;

      1

      2

      happens-before 規(guī)范 : 先行發(fā)生原則 ;

      二、指令重排序示例

      指令重排示例 :

      public class Main { // 使用 volatile 關(guān)鍵字修飾變量可以禁止指令重排 /*volatile static int x = 0; volatile static int y = 0; volatile static int a = 0; volatile static int b = 0;*/ // 沒有使用 volatile 關(guān)鍵字修飾, 會產(chǎn)生指令重排的情況 static int x = 0; static int y = 0; static int a = 0; static int b = 0; /** * 多線程運行導(dǎo)致異常值出現(xiàn), 是由于指令重排導(dǎo)致的 * @param args */ public static void main(String[] args) { // 設(shè)置一個非常大的遍歷數(shù) // 指令重排出現(xiàn)過程很少見, 基數(shù)越大, 出現(xiàn)概率越高 for (int i = 0; i < Integer.MAX_VALUE; i ++) { // 每次循環(huán)都初始化變量 x = 0; y = 0; a = 0; b = 0; // 在該線程中, 如果出現(xiàn)指令重排 // 先執(zhí)行 b = 1, 在執(zhí)行 x = a new Thread(new Runnable() { @Override public void run() { x = a; b = 1; } }).start(); // 如果出現(xiàn)指令重排 // 先執(zhí)行 a = 1, 在執(zhí)行 y = b new Thread(new Runnable() { @Override public void run() { y = b; a = 1; } }).start(); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } /* 執(zhí)行上述代碼, 不是線程 1 先執(zhí)行就是線程 2 先執(zhí)行 如果線程 1 先執(zhí)行, 則 x = 0, y = 1 如果線程 2 先執(zhí)行, 則 x = 1, y = 0 不可能出現(xiàn) x = 1, y = 1 的情況 如果出現(xiàn)了, 則說明線程內(nèi)部的執(zhí)行順序可能被顛倒了 出現(xiàn)了指令重排的情況 */ // 檢查是否有異常值出現(xiàn), 如果出現(xiàn)異常值, 退出方法 if (x == 1 && y == 1) { System.out.println("出現(xiàn)異常值 x = 1, y = 1"); return; } /*else { System.out.println("正常值 x = " + x + ", y = " + y); }*/ } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      執(zhí)行結(jié)果 :

      兩個線程的線程調(diào)度 :

      協(xié)同式調(diào)度 : 線程執(zhí)行時間 由 線程 決定 ;

      搶占式調(diào)度 : 線程執(zhí)行事件 由 系統(tǒng) 決定 ;

      【Java 并發(fā)編程】線程指令重排序問題 ( 指令重排序規(guī)范 | volatile 關(guān)鍵字禁止指令重排序 )

      上述示例中的線程調(diào)度方式是 " 搶占式調(diào)度 " , 誰先執(zhí)行

      由系統(tǒng)分配

      , 這兩個線程的執(zhí)行順序都是隨機的 , 可能線程 1 先執(zhí)行 , 也可能是線程 2 先執(zhí)行 ;

      如果線程 1 先執(zhí)行, 則 x = 0, y = 1 ;

      如果線程 2 先執(zhí)行, 則 x = 1, y = 0 ;

      根據(jù)代碼分析 , 不可能出現(xiàn) x = 1, y = 1 的情況 , 如果出現(xiàn)了, 則說明

      線程內(nèi)部的執(zhí)行順序可能被顛倒了

      , 出現(xiàn)了指令重排的情況 ;

      Java 任務(wù)調(diào)度

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:博客技術(shù)資料整理
      下一篇:java內(nèi)存模型之happenbefore原則
      相關(guān)文章
      亚洲精品欧美综合四区| 亚洲av片不卡无码久久| 国产成人亚洲综合在线| 亚洲一区精品视频在线| 亚洲男女一区二区三区| 亚洲精品美女久久久久9999| 91亚洲精品视频| 久久亚洲AV成人无码| 亚洲人成影院在线| 亚洲激情在线观看| 91亚洲国产成人精品下载| 久久精品国产亚洲av水果派| 日韩精品亚洲人成在线观看| 亚洲人成网www| 亚洲在成人网在线看| 亚洲午夜电影在线观看| 亚洲综合丁香婷婷六月香| 2020久久精品亚洲热综合一本| 亚洲AV无码无限在线观看不卡| 欧洲 亚洲 国产图片综合| 亚洲熟妇丰满xxxxx| 亚洲成在人线在线播放无码| 精品韩国亚洲av无码不卡区| 国产亚洲情侣久久精品| 亚洲男人的天堂在线va拉文| 国产亚洲精品免费视频播放| 亚洲尤码不卡AV麻豆| 亚洲AV无码专区国产乱码4SE| 亚洲精品国产成人99久久| 亚洲综合在线成人一区| 精品日韩99亚洲的在线发布| 国产成人精品亚洲2020| 亚洲av永久中文无码精品| 国产成人综合亚洲| 国产亚洲成人在线播放va| 亚洲AV永久无码精品水牛影视| 精品日韩亚洲AV无码一区二区三区 | 亚洲AV永久青草无码精品| 亚洲丝袜美腿视频| 亚洲一区二区三区久久久久| 亚洲精品无码专区|