一.synchronized的特性
??synchronized 是 Java 語言中內置的關鍵字,用于實現線程同步,以確保多線程環境下共享資源的安全訪問。
互斥性:synchronized保證了同一時刻只有一個線程可以執行被synchronized修飾的代碼塊或方法。當一個線程進入synchronized代碼塊或方法時,其他線程必須等待,直到該線程執行完畢并釋放鎖。
可重入性:同一個線程可以多次獲得同一個對象的鎖。如果一個線程已經獲取了對象的鎖,在持有鎖的情況下再次進入由synchronized修飾的代碼塊或方法,不會產生死鎖,而是允許繼續訪問。
保證可見性:synchronized不僅保證了線程的互斥執行,還保證了共享變量的可見性。當一個線程釋放鎖時,會將對共享變量的修改刷新到主內存中,而其他線程在獲取鎖時會從主內存中重新讀取該變量的值。
原子性:將代碼塊或方法聲明為synchronized可以保證其操作的原子性。即一組操作要么全部執行成功,要么全部不執行。
阻塞和喚醒機制:當一個線程嘗試獲取一個被其他線程占用的鎖時,該線程會進入阻塞狀態,直到鎖被釋放。當持有鎖的線程執行完畢并釋放鎖時,會喚醒等待的線程,使其可以繼續執行
二.synchronized的使用
synchronized關鍵字可以用于修飾方法或代碼塊,以實現線程的同步和互斥控制。
修飾方法:
public synchronized void someMethod() {// 代碼塊
}
當一個方法被synchronized修飾時,該方法被稱為同步方法。同一時刻只允許一個線程執行該方法,其他線程需要等待。該方法的鎖對象是調用該方法的實例對象(對于靜態方法,則為類對象)。同步方法的鎖范圍是整個方法體,從方法進入到結束。
修飾代碼塊:
public void someMethod() {synchronized (lockObject) {// 代碼塊}
}
通過synchronized修飾代碼塊,可以在一段具體的代碼范圍內進行同步。代碼塊中的鎖對象可以是任意對象,通常使用專門為此目的創建的對象或this關鍵字引用當前對象。同步的目的是為了保證在同一時刻只允許一個線程進入該代碼塊執行。
synchronized的使用可以保證共享數據(例如對象的實例變量)在多個線程之間的正確訪問,避免數據競爭和不一致的情況發生。當一個線程進入synchronized方法或代碼塊時,它會獲取鎖,并且在退出方法或代碼塊時釋放鎖,使得其他等待鎖的線程可以繼續執行。
三.synchronized的鎖機制
對象鎖:synchronized 關鍵字使用對象鎖來實現同步。每個對象都有一個內置的鎖(monitor)和一個與之關聯的等待隊列。
? 鎖獲取:當一個線程進入同步代碼塊或同步方法時,將嘗試獲取與鎖對象關聯的 monitor。如果 monitor 未被其他線程占用,該線程將獲得鎖并執行同步代碼;如果 monitor 被其他線程占用,該線程將進入等待隊列并等待鎖。
? 鎖釋放:當線程執行完同步代碼塊或同步方法后,它將釋放鎖并喚醒等待隊列中的一個線程(如果存在)。
需要注意的是,synchronized的鎖是非公平的。這意味著當多個線程同時競爭一個對象的鎖時,無法保證哪個線程會獲得鎖。通常情況下,JVM會選擇一個等待時間最長的線程來獲得鎖。
除了內置的對象鎖之外,Java還提供了其他類型的鎖,如ReentrantLock和ReadWriteLock,它們提供了更高級的鎖機制,如可重入、公平性控制、條件變量等特性