【多線程】synchonized 實現過程

synchronized 關鍵字是 Java 中用於實現線程同步的一種機制,旨在確保多個線程在執行同步代碼塊時的原子性和可見性。synchronized 可以用於方法或者代碼塊上,以確保同一時刻只有一個線程可以執行被同步的代碼。

synchronized 的實現過程

1. 鎖的獲取和釋放

2. 底層實現

在 JVM 層面,synchronized 關鍵字的實現依賴於內部的鎖機制(也稱爲監視器鎖或互斥鎖)。Java 的每個對象都有一個與之關聯的監視器鎖。

3. 鎖的升級和優化

從 JDK 1.6 開始,JVM 對 synchronized 關鍵字實現進行了大量的優化,包括鎖的升級策略,以減少鎖的競爭所導致的系統開銷。

示例演示

示例一:方法級別的同步

public class Counter {
    private int count = 0;

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

    public synchronized void decrement() {
        count--;
    }

    public synchronized int getCount() {
        return count;
    }

    public static void main(String[] args) {
        Counter counter = new Counter();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.decrement();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final Count: " + counter.getCount());
    }
}

在這個示例中,Counter 類的 incrementdecrement 和 getCount 方法都被 synchronized 修飾,這意味着這些方法在同一時間只能被一個線程訪問。

當 thread1 和 thread2 分別調用 increment 和 decrement 方法時,它們會競爭對 count 變量的訪問。

由於 synchronized 關鍵字的存在,確保了每次只有一個線程可以執行這些方法,從而避免了多線程環境下的數據不一致問題。

示例二:代碼塊級別的同步

public class SafeCounter {
    private int count = 0;
    private final Object lock = new Object();

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

    public void decrement() {
        synchronized (lock) {
            count--;
        }
    }

    public int getCount() {
        synchronized (lock) {
            return count;
        }
    }

    public static void main(String[] args) {
        SafeCounter counter = new SafeCounter();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.decrement();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final Count: " + counter.getCount());
    }
}

在這個示例中,incrementdecrement 和 getCount 方法內部使用了 synchronized 代碼塊,而不是修飾整個方法。

這裏使用了一個自定義的鎖對象 lock 來實現同步。

這種方式提供了更高的靈活性,因爲它允許在方法內部只對需要同步的代碼塊進行加鎖,而不是整個方法。

這有助於提高程序的併發性能。

示例三:靜態方法的同步

public class StaticCounter {
    private static int count = 0;

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

    public synchronized static void decrement() {
        count--;
    }

    public synchronized static int getCount() {
        return count;
    }

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                decrement();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final Count: " + getCount());
    }
}

在這個示例中,StaticCounter 類的 incrementdecrement 和 getCount 方法都被聲明爲 static 並用 synchronized 修飾。

這意味着它們鎖定的是 StaticCounter 類的 Class 對象,而不是類的某個實例。當 thread1 和 thread2 分別調用這些靜態方法時,它們會競爭對 count 變量的訪問。

由於 synchronized 關鍵字的存在,確保了每次只有一個線程可以執行這些方法,從而避免了多線程環境下的數據不一致問題。

這些示例展示了 synchronized 關鍵字在不同場景下的應用,包括方法級別的同步、代碼塊級別的同步以及靜態方法的同步。

通過正確使用 synchronized,可以在多線程編程中確保線程安全。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Mq_LGyXp0ulFh3LbNMIGGA