日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java 并发编程】线程操作原子性问题 ( 问题业务场景分析 | 使用 synchronized 解决线程原子性问题 )

發布時間:2025/6/17 java 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java 并发编程】线程操作原子性问题 ( 问题业务场景分析 | 使用 synchronized 解决线程原子性问题 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 總結
  • 一、原子性問題示例
  • 二、線程操作原子性問題分析
  • 三、使用 synchronized 解決線程原子性問題

總結


原子操作問題 : 線程中 , 對變量副本 count 進行自增操作 , 不是原子操作 , 首先 從工作內存中讀取變量副本到執行引擎 ( 操作數棧 ) 中 , 然后進行自增運算 , 最后 寫回到線程工作內存中 , 這是 333 個操作 , 如果變量 在這 333 個操作的空檔時間進行了修改 , 那么就會產生無法預知的效果 ;


總結一下 : 線程 A 的變量副本入操作數棧的時刻 , 該共享變量被線程 B 修改并且同步更新 , 此時入棧的這個變量自增是無效的 , 但是也算自增了 111 次 , 因此這里就丟失了 111 次計算機會 ;





一、原子性問題示例



開啟 202020 個線程 , 對某個線程共享 int 類型變量進行自增 , 每個線程自增 100001000010000 次 , 那么按照正常執行 , 202020 個線程執行完畢后的變量值應該是 200000200000200000 ;


代碼示例 :

public class Main {private volatile static int count = 0;private static void increase() {count++;}public static void main(String[] args) {for (int i = 0; i < 20; i ++) {new Thread(){@Overridepublic void run() {for (int i = 0; i < 10000; i ++) {increase();System.out.println(count);}}}.start();}} }

執行結果 : 多運行幾次 , 有的時候會出現結果不是 200000 的情況 , 這就是出現問題的情景 ;





二、線程操作原子性問題分析



上述程序中 , 將變量 int count 設置成 volatile 類型的 , 只能保證其 可見性有序性 , 無法保證 線程操作的 原子性 ;

在線程中對 int count = 0 進行累加操作 , 首先將變量 int count = 0 加載到線程工作內存的變量副本中 , 這里創建了 202020 個線程 , 就會有 202020 個線程對應的工作內存空間 , 需要將 count 變量拷貝 202020 份到相應的線程工作內存中 ;


有這樣一種極端情況 , 當某個線程 A , 將 變量副本 加載到 線程執行引擎 時 , 就是 線程棧 中的 棧幀 的的 操作數棧 中 , 此時將要開始執行相關操作 , 在線程執行引擎沒有執行之前 ,

與此同時 , 線程 B 修改了 count 副本變量 , 并進行了同步 , 主內存 , 包括 線程 A 的副本變量也已經更新了最新的值 ,

當前 線程棧中的棧幀中的操作數棧 中 , 還壓著一個副本變量 , 雖然 該變量已經過時 , 該 count++ 操作無效 , 這樣就 丟失了 111 次 count 變量自增的操作 , 導致 最終輸出的值是 199991999919999 ;


原子操作問題 : 線程中 , 對變量副本 count 進行自增操作 , 不是原子操作 , 首先 從工作內存中讀取變量副本到執行引擎 ( 操作數棧 ) 中 , 然后進行自增運算 , 最后 寫回到線程工作內存中 , 這是 333 個操作 , 如果變量 在這 333 個操作的空檔時間進行了修改 , 那么就會產生無法預知的效果 ;


總結一下 : 線程 A 的變量副本入操作數棧的時刻 , 該共享變量被線程 B 修改并且同步更新 , 此時入棧的這個變量自增是無效的 , 但是也算自增了 111 次 , 因此這里就丟失了 111 次計算機會 ;





三、使用 synchronized 解決線程原子性問題



使用 synchronized 修飾 increase 方法 ;

private static void increase() {count++;}

方法 , 相當于在方法體重添加了 synchronized 代碼塊 ;

private static void increase() {synchronized (Main.class) {count++;}}

一旦某個線程執行 synchronized 方法或代碼塊中的代碼 , 則當前線程持有互斥鎖 , 只能由當前線程訪問 count 變量 ;


代碼示例 :

public class Main {private volatile static int count = 0;private synchronized static void increase() {count++;}public static void main(String[] args) {for (int i = 0; i < 20; i ++) {new Thread(){@Overridepublic void run() {for (int i = 0; i < 10000; i ++) {increase();System.out.println(count);}}}.start();}} }

執行結果 :

總結

以上是生活随笔為你收集整理的【Java 并发编程】线程操作原子性问题 ( 问题业务场景分析 | 使用 synchronized 解决线程原子性问题 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。