【轉】[Java] 防止併發的多種寫法

z5337發表於2024-04-29

來自:阿里的 通義靈碼

要確保在Java中同一方法被多個執行緒同時呼叫時,只有其中一個成功執行,可以採用幾種併發控制策略。以下是幾種實現方式:

1. 使用ReentrantLock的tryLock()

import java.util.concurrent.locks.ReentrantLock;

public class SingletonExecution {
    private static final ReentrantLock lock = new ReentrantLock();

    public boolean executeOnce() {
        // 嘗試獲取鎖,如果已經鎖住則立即返回false,否則獲取鎖並執行
        if (lock.tryLock()) {
            try {
                // 執行業務邏輯
                performAction();
                return true; // 成功執行
            } finally {
                lock.unlock(); // 確保鎖被釋放
            }
        } else {
            // 鎖已被其他執行緒持有,表示已有其他呼叫者成功
            return false;
        }
    }

    private void performAction() {
        // 實際執行的業務邏輯
    }
}

2. 使用synchronized和標誌位

public class SingletonExecution {
    private static boolean executed = false;

    public synchronized boolean executeOnce() {
        if (!executed) {
            // 執行業務邏輯
            performAction();
            executed = true;
            return true;
        }
        return false; // 已經有其他執行緒執行過了
    }

    private void performAction() {
        // 實際執行的業務邏輯
    }
}

3. 使用AtomicBoolean和CAS操作

import java.util.concurrent.atomic.AtomicBoolean;

public class SingletonExecution {
    private static final AtomicBoolean executed = new AtomicBoolean(false);

    public boolean executeOnce() {
        // 使用CAS操作,如果executed為false則設定為true並返回true,否則返回false
        return executed.compareAndSet(false, true);
    }

    // 這裡可以新增執行的業務邏輯方法
}

每種方法都有其適用場景。使用tryLock()提供了非阻塞的嘗試獲取鎖的方式,適合於那些不希望執行緒等待的情況。

synchronizedAtomicBoolean則分別利用內建鎖和原子操作保證操作的原子性和可見性,適用於簡單場景。

選擇時應考慮具體需求,如是否需要阻塞、效能要求等因素。

相關文章