synchronized的用法


synchronized和volatile關鍵字的用法和區別

1. synchronized關鍵字

1. 介紹

synchronized關鍵字是java提供的鎖機制, 主要解決線程同步的問題, 那么它可以修飾方法和同步代碼塊, 鎖使用的范圍一般情況是越小越好

2. 原理

synchronized是通過對象內部的一個叫做監視器鎖(monitor)來實現的. 但是監視器鎖本質又是依賴於底層的操作系統的互斥鎖(Mutex Lock)來是實現的. 而操作系統實現線程之間的切換這就需要從用戶態轉換到核心態, 這個成本非常高, 狀態之間的轉換需要相對比較長的時間, 這就是為什么synchronized效率低的原因. 這種依賴於操作系統互斥鎖鎖是吸納的鎖, 我們稱之為重量級鎖

3. synchronized的兩種用法

public class ATest {

    // 作用在方法上的synchronized關鍵字
    public synchronized void method1() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
    // 作用在代碼塊的synchronized關鍵字
    public void method2() {
        synchronized (this) {
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        }
    }
}

4. 單例模式

public class Singleton {

  private static Singleton instance = null;

  private Singleton() { }

  public static Singleton getInstance() {

     if(instance == null) {

        synchronzied(Singleton.class) {

           if(instance == null) {

               instance = new Singleton();  //非原子操作

           }

        }

     }

     return instance;

   }

}

2. volatile關鍵字

參考: https://www.cnblogs.com/dolphin0520/p/3920373.html

正確使用 volatile 變量的條件

您只能在有限的一些情形下使用 volatile 變量替代鎖。要使 volatile 變量提供理想的線程安全,必須同時滿足下面兩個條件:

  • 對變量的寫操作不依賴於當前值。
  • 該變量沒有包含在具有其他變量的不變式中。

實際上,這些條件表明,可以被寫入 volatile 變量的這些有效值獨立於任何程序的狀態,包括變量的當前狀態。

第一個條件的限制使 volatile 變量不能用作線程安全計數器。雖然增量操作(x++)看上去類似一個單獨操作,實際上它是一個由讀取-修改-寫入操作序列組成的組合操作,必須以原子方式執行,而 volatile 不能提供必須的原子特性。實現正確的操作需要使 x 的值在操作期間保持不變,而 volatile 變量無法實現這點。(然而,如果將值調整為只從單個線程寫入,那么可以忽略第一個條件。)

3. synchronized和volatile的區別

一旦一個共享變量(類的成員變量、類的靜態成員變量)被volatile修飾之后,那么就具備了兩層語義:
1)保證了不同線程對這個變量進行操作時的可見性,即一個線程修改了某個變量的值,這新值對其他線程來說是
立即可見的。
2)禁止進行指令重排序。
volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取;
synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。

1.volatile僅能使用在變量級別;
synchronized則可以使用在變量、方法、和類級別的

2.volatile僅能實現變量的修改可見性,並不能保證原子性;

synchronized則可以保證變量的修改可見性和原子性

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM