亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

volatile和synchronize有哪些區別

發布時間:2020-11-20 09:46:56 來源:億速云 閱讀:408 作者:小新 欄目:編程語言

小編給大家分享一下volatile和synchronize有哪些區別,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

區別:1、volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。2、volatile保證數據的可見性,但不能保證原子性;而synchronized可以保證原子性,也可以間接保證可見性。

可見性(visibility)

可見性:一個線程對共享變量做了修改之后,其他的線程立即能夠看到(感知到)該變量這種修改(變化)。
Java內存模型是通過將在工作內存中的變量修改后的值同步到主內存,在讀取變量前從主內存刷新最新值到工作內存中,這種依賴主內存的方式來實現可見性的。

原子性(atomicity)

原子性:一個操作不能被打斷,要么全部執行完畢,要么不執行。
java內存模型所保證的是,同線程內,所有的操作都是由上到下的,但是多個線程并行的情況下,則不能保證其操作的有序性。

有序性

有序性:在本線程內觀察,操作都是有序的;如果在一個線程中觀察另外一個線程,所有的操作都是無序的。

java內存模型所保證的是,同線程內,所有的操作都是由上到下的,但是多個線程并行的情況下,則不能保證其操作的有序性。
計算機在執行程序時,為了提高性能,編譯器個處理器常常會對指令做重排,一般分為以下 3 種
volatile和synchronize有哪些區別
單線程環境里面確保程序最終執行的結果和代碼執行的結果一致
處理器在進行重排序時必須考慮指令之間的數據依賴性
多線程環境中線程交替執行,由于編譯器優化重排的存在,兩個線程中使用的變量能否保證用的變量能否一致性是無法確定的,結果無法預測
考試先做會做的,不會做的后做。

public void mySort(){
int x = 11; //1
int y = 12; //2
x= x+5; // 3
y = x*x;//4

可能的順序1234 2134 1324,不可能的屬性4在1 和3前,因為有數據依賴性。

volatile和synchronize有哪些區別
volatile禁止指令重排。

public class ReSortSeqDemo {
    int a = 0;
    boolean flag = false;
    
    public void method01() {
        a = 1;           // flag = true;
                         // ----線程切換----
        flag = true;     // a = 1;
    }

    public void method02() {
        if (flag) {
            a = a + 3;
            System.out.println("a = " + a);
        }
    }

}

如果兩個線程同時執行,method01 和 method02 如果線程 1 執行 method01 重排序了,然后切換的線程 2 執行 method02 就會出現不一樣的結果。

禁止指令排序

volatile 實現禁止指令重排序的優化,從而避免了多線程環境下程序出現亂序的現象

先了解一個概念,內存屏障(Memory Barrier)又稱內存柵欄,是一個 CPU 指令,他的作用有兩個:

保證特定操作的執行順序
保證某些變量的內存可見性(利用該特性實現 volatile 的內存可見性)
由于編譯器個處理器都能執行指令重排序優化,如果在指令間插入一條 Memory Barrier 則會告訴編譯器和 CPU,不管什么指令都不能個這條 Memory Barrier 指令重排序,也就是說通過插入內存屏障禁止在內存屏障前后執行重排序優化。內存屏障另一個作用是強制刷出各種 CPU 緩存數據,因此任何 CPU 上的線程都能讀取到這些數據的最新版本。

下面是保守策略下,volatile寫插入內存屏障后生成的指令序列示意圖:
volatile和synchronize有哪些區別
下面是在保守策略下,volatile讀插入內存屏障后生成的指令序列示意圖:
volatile和synchronize有哪些區別

線程安全性保證

工作內存與主內存同步延遲現象導致可見性問題
可以使用 synchronzied 或 volatile 關鍵字解決,它們可以使用一個線程修改后的變量立即對其他線程可見
對于指令重排導致可見性問題和有序性問題
可以利用 volatile 關鍵字解決,因為 volatile 的另一個作用就是禁止指令重排序優化

volatile

它所修飾的變量不保留拷貝,直接訪問主內存中的。

在Java內存模型中,有main memory,每個線程也有自己的memory (例如寄存器)。為了性能,一個線程會在自己的memory中保持要訪問的變量的副本。這樣就會出現同一個變量在某個瞬間,在一個線程的memory中的值可能與另外一個線程memory中的值,或者main memory中的值不一致的情況。 一個變量聲明為volatile,就意味著這個變量是隨時會被其他線程修改的,因此不能將它cache在線程memory中。

使用場景

您只能在有限的一些情形下使用 volatile 變量替代鎖。要使 volatile 變量提供理想的線程安全,必須同時滿足下面兩個條件:
1)對變量的寫操作不依賴于當前值。
2)該變量沒有包含在具有其他變量的不變式中。

volatile最適用一個線程寫,多個線程讀的場合。
如果有多個線程并發寫操作,仍然需要使用鎖或者線程安全的容器或者原子變量來代替。

synchronized

當它用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多只有一個線程執行該段代碼

  1. 當兩個并發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以后才能執行該代碼塊。
  2. 然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。
  3. 尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。
  4. 當一個線程訪問object的一個synchronized(this)同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞
    volatile和synchronize有哪些區別
    共享資源及增刪改的對象。

Lock

從jdk 5.0開始,java提供了更強大的線程同步機制-通過顯示定義同步鎖對象來實現同步,同步鎖使用Lock對象充當。

java.util.concurrent.Locks.Lock接口是控制多個線程對共享資源進行訪問的工具。鎖提供了對共享資源的獨占訪問,每次只能有一個線程對Lock對象加鎖,線程開始訪問共享資源之前應先獲得Lock對象。

ReentrantLock類實現了Lock,它擁有與synchronized相同的并發性和內存語義,在實現線程安全的控制中,比較常用的是ReentrantLock,可以顯示加鎖、釋放鎖。

volatile和synchronize有哪些區別

區別

volatile和synchronized

  • volatile是變量修飾符,而synchronized則作用于一段代碼或方法

  • volatile只是在線程內存和“主”內存間同步某個變量的值;而synchronized通過鎖定和解鎖某個監視器同步所有變量的值, 顯然synchronized要比volatile消耗更多資源。

  • volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。

  • volatile保證數據的可見性,但不能保證原子性;而synchronized可以保證原子性,也可以間接保證可見性,因為它會將私有內存中和公共內存中的數據做同步。

  • volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化。

線程安全包含原子性和可見性兩個方面,Java的同步機制都是圍繞這兩個方面來確保線程安全的。
關鍵字volatile主要使用的場合是在多個線程中可以感知實例變量被修改,并且可以獲得最新的值使用,也就是多線程讀取共享變量時可以獲得最新值使用。

關鍵字volatile提示線程每次從共享內存中讀取變量,而不是私有內存中讀取,這樣就保證了同步數據的可見性。但是要注意的是:如果修改實例變量中的數據

例如:i++,也就是i=i+1,則這樣的操作其實并不是一個原子操作,也就是非線程安全的。表達式i++操作步驟分解如下:
1)從內存中取出i的值。
2)計算i的值;
3)將i的值寫到內存中。
假如在第2步計算值得時候,另外一個線程也修改i的值,name這個時候就會出現臟讀數據。解決的辦法就是使用synchronized關鍵字。 所以說volatile本身并不處理數據的原子性,而是強制對數據的讀寫及時的影響到主內存中。

synchronized 和Lock

Lock是顯示鎖(手動開啟和關閉,別忘記關閉鎖),synchronized是隱式鎖,出了作用域自動釋放鎖。
Lock只有代碼塊鎖,synchronized可以作用代碼塊和方法。
使用Lock鎖,jvm花費較少的時間來調度線程,性能更好。并且具有更好的擴展性(提供更多的子類)。
使用順序:Lock->同步代碼塊(已經進入了方法體,分配了相應資源)->同步方法(在方法體之外)。

以上是volatile和synchronize有哪些區別的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

华阴市| 合肥市| 房产| 永泰县| 固镇县| 普安县| 土默特左旗| 项城市| 宁安市| 祁东县| 都昌县| 大石桥市| 探索| 远安县| 淳安县| 布拖县| 高淳县| 安龙县| 内丘县| 定南县| 道孚县| 徐水县| 通州市| 洪湖市| 阿坝县| 内丘县| 邮箱| 榆社县| 固始县| 宁远县| 顺义区| 丰台区| 湾仔区| 通海县| 宁国市| 济源市| 珲春市| 垫江县| 上虞市| 临城县| 沐川县|