首頁 > 軟體

一文帶你搞懂Java中Synchronized和Lock的原理與使用

2023-10-16 22:00:20

1、Synchronized與Lock對比

  • 實現方式:Synchronized是Java語言內建的關鍵字,而Lock是一個Java介面。
  • 鎖的獲取和釋放:Synchronized是隱式獲取和釋放鎖,由Java虛擬機器器自動完成;而Lock需要顯式地呼叫lock()方法獲取鎖,並且必須在finally塊中呼叫unlock()方法來釋放鎖。
  • 可中斷性:在獲取鎖的過程中,如果執行緒被中斷,synchronized會丟擲InterruptedException異常並且自動釋放鎖,而Lock則需要手動捕獲InterruptedException異常並處理,同時也支援非阻塞、可輪詢以及定時獲取鎖的方式。
  • 公平性:Synchronized不保證執行緒獲取鎖的公平性,而Lock可以通過建構函式指定公平或非公平鎖。
  • 鎖狀態:Synchronized無法判斷鎖的狀態,而Lock可以通過tryLock()、isLocked()來判斷鎖的狀態(執行緒是否可能取到鎖、鎖是否被佔用等)。
  • 粒度:Synchronized鎖的粒度較粗,只能鎖住整個方法或程式碼塊,而Lock可以細粒度地控制鎖的範圍,比如鎖某個物件的部分屬性。
  • 場景:如果在簡單的並行場景下,推薦使用Synchronized;而在需要更高階的鎖控制時,可以考慮使用Lock。

一般情況建議使用Synchronized,在JDK1.5之前Lock優於Synchronized,但在JDK1.5之後對Synchronized進行了優化,後面在效能方面基本與Lock一樣且使用簡單(有作者說"Synchronized是親生的,JDK還是會一直優化他不會讓Lock優於它")。

2、Synchronized與Lock原理

2.1 Synchronized原理

Synchronized是Java語言中最常用的同步機制之一,它可以確保多個執行緒存取共用資源時的互斥性和可見性。Synchronized關鍵字的原理如下:

  • Synchronized使用了內建鎖(也稱為監視器鎖)來實現同步。每個Java物件都有一個內建鎖,當該物件作為鎖被獲取時,其他試圖獲取該鎖的執行緒會被阻塞,直到該鎖被釋放。
  • Synchronized的鎖是與物件相關聯的。當一個執行緒進入Synchronized程式碼塊時,它必須先獲取該物件的鎖才能執行程式碼,否則就會被阻塞。當該執行緒退出Synchronized程式碼塊時,它會自動釋放該物件的鎖。
  • Synchronized具有可重入性。如果當前執行緒已經獲得了某個物件的鎖,那麼它可以繼續存取該物件的其他Synchronized程式碼塊,而不會被自己持有的鎖所阻塞。
  • Synchronized還具有volatile變數的讀寫語意。在使用Synchronized關鍵字時,記憶體屏障會確保本地執行緒中修改過的變數值被重新整理回主記憶體,從而保證了多個執行緒之間對變數修改的可見性。

Synchronized通過使用內建鎖、與物件關聯的鎖、可重入性以及記憶體屏障等機制來實現執行緒的同步和鎖的管理,以保證對共用資源的存取具有互斥性和可見性。

2.2 Lock原理

Lock是Java語言中的一種高階同步機制,它提供了比Synchronized更加靈活和可延伸的同步特性。Lock機制的原理如下:

  • Lock使用了物件的鎖來實現同步。每個Lock物件都有一個鎖,當該鎖被獲取時,其他試圖獲取該鎖的執行緒會被阻塞,直到該鎖被釋放。
  • Lock的鎖是與物件無關的。相比於Synchronized關鍵字,Lock提供了更加靈活的方式來控制鎖的獲取和釋放。例如,它支援可中斷的獲取鎖操作、超時獲取鎖操作等等。因此,在需要手動控制鎖的獲取和釋放時,Lock是一個很好的選擇。
  • Lock還具有可重入性。如果當前執行緒已經獲得了某個Lock物件的鎖,那麼它可以繼續存取該物件的其他Lock程式碼塊,而不會被自己持有的鎖所阻塞。
  • Lock使用了條件變數來實現執行緒的等待和通知。Condition介面提供了await()、signal()和signalAll()等方法,用於執行緒之間的等待和通知,從而避免了Object類中wait()和notify()方法可能出現的訊號丟失問題。

Lock通過使用物件的鎖、與物件無關的鎖、可重入性以及條件變數等機制來實現執行緒的同步和鎖的管理,以保證對共用資源的存取具有互斥性和可見性。與Synchronized關鍵字相比,Lock提供了更加靈活和可延伸的同步特性,但也需要更多的程式碼來控制鎖的獲取和釋放。

3、Synchronized與Lock使用

下面分別給出Synchronized和Lock的使用範例。

Synchronized

    public class Counter {
        private int count;

        public synchronized void increment() {
            count++;
        }
    }

上述程式碼定義了一個計數器類Counter,方法都使用了synchronized關鍵字來實現執行緒同步。

Lock

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Counter {
    private int count;
    private Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}

上述程式碼也是定義了一個計數器類Counter,但是使用的是Lock介面來實現執行緒同步。在這種情況下,需要先建立一個ReentrantLock物件,然後在需要同步的程式碼塊中呼叫lock()方法獲取鎖,在finally塊中呼叫unlock()方法釋放鎖。

總的來說,Synchronized更加簡單易用,適合用於一些簡單的並行場景;而Lock提供了更多的靈活性和可延伸性,適合用於一些複雜的並行場景。

4、相關問題

1)Synchronized和Lock有什麼區別?

  • 實現方式:Synchronized是Java內建的關鍵字,而Lock是一個介面。
  • 鎖的獲取和釋放:Synchronized的獲取和釋放鎖由JVM自動完成,而Lock需要手動呼叫lock()方法獲取鎖並在finally塊中呼叫unlock()方法釋放鎖。
  • 可中斷性:如果執行緒在獲取鎖的過程中被中斷,Synchronized會丟擲InterruptedException異常並自動釋放鎖,而Lock需要手動處理這種情況。
  • 公平性:Synchronized不保證公平性,而Lock可以通過建構函式指定公平或非公平鎖。
  • 粒度:Synchronized鎖的粒度比較粗,只能鎖住整個方法或程式碼塊,而Lock可以細粒度地控制鎖的範圍。

2)Synchronized的實現原理是什麼?

Synchronized是基於Java物件頭的監視器(Monitor)實現的。每個Java物件都有一個監視器,同步塊的進入和退出需要獲取和釋放物件的監視器。當執行緒嘗試進入一個被鎖住的同步塊時,它會先嚐試獲取物件的監視器鎖,如果鎖已經被佔用,執行緒就會進入阻塞狀態,直到鎖被釋放。

3)Lock的實現原理是什麼?

Lock的實現是基於Java的AbstractQueuedSynchronizer(AQS)框架的。Lock介面定義了多個獲取和釋放鎖的方法,其中比較重要的是lock()和unlock()方法。當一個執行緒呼叫lock()方法獲取鎖時,如果鎖未被佔用,則該執行緒會佔用鎖並繼續執行;否則,該執行緒會進入阻塞狀態,直到鎖被釋放。當一個執行緒呼叫unlock()方法釋放鎖時,會通知等待佇列中的其他執行緒繼續嘗試獲取鎖。

4)什麼是可重入鎖?

可重入鎖指的是同一個執行緒在持有鎖的情況下,能夠再次獲取該鎖,而不會導致死鎖。Synchronized和ReentrantLock都是可重入鎖。可重入鎖通過記錄持有鎖的執行緒和重入次數,來避免死鎖的發生。

5)ReentrantLock為什麼比Synchronized更靈活?

ReentrantLock比Synchronized更靈活主要因為它提供了以下功能:

  • 可以指定公平鎖或非公平鎖。
  • 支援獲取鎖的超時時間。
  • 支援可中斷的獲取鎖操作。
  • 可以通過tryLock()方法嘗試獲取鎖,如果鎖已經被佔用,則返回false。
  • 支援多個Condition物件,可以讓執行緒在不同的條件下等待和喚醒。

6)什麼是鎖自旋?

鎖自旋是一種優化鎖競爭的技術,它用於減少執行緒在獲取鎖時的等待時間。當一個執行緒請求獲取某個物件的鎖時,如果此時鎖已經被其他執行緒佔用,那麼該執行緒會進入阻塞狀態等待鎖的釋放。而使用鎖自旋技術,執行緒在發現鎖被其他執行緒佔用時,並不會立即進入阻塞狀態,而是執行一段迴圈程式碼(稱為自旋),等待鎖的持有者釋放鎖。

以上就是一文帶你搞懂Java中Synchronized和Lock的原理與使用的詳細內容,更多關於Java Synchronized Lock的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com