簡體   English   中英

微調Java同步塊行為

[英]Fine-tuning Java synchronized block behavior

我有兩個同步的代碼塊。 我需要兩個代碼塊不能在兩個或多個不同的線程中同時運行,但是我允許兩個或多個不同的線程同時運行一個代碼塊。 用Java如何做到這一點? 舉例說明:

class HelloWorld {

    method1() {
        synchronized (?) { //block 'A'
            //I want to allow 2+ threads to run this code block simultaneously
        }
    }

    method2() {
        synchronized (?) { //block 'B'
            //this should block while another thread is running
            //the synchronized block 'A'
        }
    }

我不希望兩個同步塊都鎖定在同一對象/類上,因為這將不允許第一個塊同時由多個線程運行。 但是,這是防止塊A和B由2個或更多線程同時運行的唯一方法。 必須有一種方法來實現這一目標。

我建議分別研究ReadWriteLock實現類ReentrantReadWriteLock 那個東西特別是被設計成允許多個 “閱讀器”線程。 但只有一個 “作家”線程。

如果我正確閱讀了您的問題,那正是您所要的。 另一方面,退后一步並闡明您要在此處解決的真正問題可能也是明智的。

特別是考慮到上述鎖在Java8上可以很好地工作,但是在Java的早期版本中卻遇到了問題。

也許像這樣:

private CommonStateSynchronizer synchronizer = new CommonStateSynchronizer();

public void method1() throws InterruptedException
{
    synchronizer.run("method1", () -> {
        // do method1
    });
}

public void method2() throws InterruptedException
{
    synchronizer.run("method2", () -> {
        // do method2
    });
}

public static class CommonStateSynchronizer
{
    private final ReentrantReadWriteLock rw;
    private final ReentrantReadWriteLock.ReadLock r; // hold read lock while executing in current state
    private final ReentrantReadWriteLock.WriteLock w; // hold write lock while checking or changing state
    private final Condition stateChanged;
    private volatile String currentState; // do not modify unless holding write lock

    public CommonStateSynchronizer()
    {
        rw = new ReentrantReadWriteLock(true);
        r = rw.readLock();
        w = rw.writeLock();
        stateChanged = w.newCondition();
    }

    public void run(String state, Runnable runnable) throws InterruptedException {
        w.lock();

        while (!state.equals(currentState))
        {
            if (currentState == null)
            {
                currentState = state;
                stateChanged.notifyAll();
                break;
            }
            stateChanged.await();
        }
        assert state.equals(currentState);

        // downgrade to concurrent read lock
        r.lock();
        w.unlock();

        try
        {
            runnable.run();
        }
        finally
        {
            r.unlock();
            w.lock();

            if (rw.getReadLockCount() == 0)
            {
                currentState = null;
                stateChanged.notifyAll();
            }
            w.unlock();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM