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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 线程安全的原因_java的多线程:java安全问题产生的原因与JMM的关系

發布時間:2025/3/12 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 线程安全的原因_java的多线程:java安全问题产生的原因与JMM的关系 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、多線程產生安全問題

1、Java內存模型
共享內存模型指的就是Java內存模型(簡稱JMM),JMM決定一個線程對共享變量的寫入時,能對另一個線程可見。

從抽象的角度來看,JMM定義了線程和主內存之間的抽象關系:

線程之間的共享變量存儲在主內存(main memory)中,每個線程都有一個私有的本地內存(local memory),本地內存中存儲了該線程以讀/寫共享變量的副本。

本地內存是JMM的一個抽象概念,并不真實存在。它涵蓋了緩存,寫緩沖區,寄存器以及其他的硬件和編譯器優化。

1.主內存:存放多線程操作的共享變量 比如count=0

2.本地內存:存儲了當前該線程以讀/寫共享變量的副本,副本 count1=0,count2=0

多線程同時進行變量操作時比如,對count進行++,先對副本進行++為1,將副本刷新到主內存,由于兩個線程是不可見的,共享變量變為1,理論為2,但是還是1 ,

2.不可見

3.可見性

線程A與線程B之間如要通信的話,必須要經歷下面2個步驟:

  • 首先,線程A把本地內存A中更新過的共享變量刷新到主內存中去。

  • 然后,線程B到主內存中去讀取線程A之前已更新過的共享變量。

  • 下面通過示意圖來說明這兩個步驟:

    二、Volatile

    什么是Volatile

    可見性也就是說一旦某個線程修改了該被volatile修飾的變量,它會保證修改的值會立即被更新到主存,當有其他線程需要讀取時,可以立即獲取修改之后的值。

    在Java中為了加快程序的運行效率,對一些變量的操作通常是在該線程的寄存器或是CPU緩存上進行的,之后才會同步到主存中,而加了volatile修飾符的變量則是直接讀寫主存。

    Volatile 保證了線程間共享變量的及時可見性,但不能保證原子性

    class ThreadVolatileDemo extends Thread {public boolean flag = true;@Overridepublic void run() {undefinedSystem.out.println("開始執行子線程....");while (flag) {undefined}System.out.println("線程停止");}public void setRuning(boolean flag) {this.flag = flag;}}public class ThreadVolatile {public static void main(String[] args) throws InterruptedException {ThreadVolatileDemo threadVolatileDemo = new ThreadVolatileDemo();threadVolatileDemo.start();Thread.sleep(3000);threadVolatileDemo.setRuning(false);System.out.println("flag 已經設置成false");Thread.sleep(1000);System.out.println(threadVolatileDemo.flag);}}

    運行結果:

    已經將結果設置為fasle為什么?還一直在運行呢。

    原因:線程之間是不可見的,讀取的是副本,沒有及時讀取到主內存結果。

    解決辦法使用Volatile關鍵字將解決線程之間可見性, 強制線程每次讀取該值的時候都去“主內存”中取值

    2、Volatile特性

    1.保證此變量對所有的線程的可見性,這里的“可見性”,如本文開頭所述,當一個線程修改了這個變量的值,volatile 保證了新值能立即同步到主內存,以及每次使用前立即從主內存刷新。但普通變量做不到這點,普通變量的值在線程間傳遞均需要通過主內存(詳見:Java內存模型)來完成。

    2.禁止指令重排序優化。有volatile修飾的變量,賦值后多執行了一個“load addl $0x0, (%esp)”操作,這個操作相當于一個內存屏障(指令重排序時不能把后面的指令重排序到內存屏障之前的位置),只有一個CPU訪問內存時,并不需要內存屏障;(什么是指令重排序:是指CPU采用了允許將多條指令不按程序規定的順序分開發送給各相應電路單元處理)。

    volatile 性能:

    volatile 的讀性能消耗與普通變量幾乎相同,但是寫操作稍慢,因為它需要在本地代碼中插入許多內存屏障指令來保證處理器不發生亂序執行。

    (1)從而我們可以看出volatile雖然具有可見性但是并不能保證原子性。

    (2)性能方面,synchronized關鍵字是防止多個線程同時執行一段代碼,就會影響程序執行效率,而volatile關鍵字在某些情況下性能要優于synchronized。

    但是要注意volatile關鍵字是無法替代synchronized關鍵字的,因為volatile關鍵字無法保證操作的原子性。

    總結

    以上是生活随笔為你收集整理的java 线程安全的原因_java的多线程:java安全问题产生的原因与JMM的关系的全部內容,希望文章能夠幫你解決所遇到的問題。

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