2016-11-04 65 views
1

我有兩個同步的代碼塊。我需要兩個代碼塊不能同時在兩個或更多不同的線程中運行,但我會想要允許兩個或更多個不同的線程同時運行代碼塊的一個一個。這怎麼能在Java中完成?爲了舉例說明:微調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個或更多線程的唯一途徑。必須有一種方法來實現這一點。

+1

我會重新考慮你爲什麼需要這個,因爲最有可能實現您的解決方案的方式,所以這是不是必需的。 –

+1

爲什麼名爲HelloWorld的類?這是你第一次嘗試Java嗎?如果是這樣,遠離併發。 – Kayaman

+0

卡亞曼,班級名稱有什麼不同?這是您第一次嘗試提供有用的評論嗎? – bitsmcgee77

回答

2

我建議分別查看ReadWriteLock執行類ReentrantReadWriteLock。這件事是專門設計允許多個「讀者」線程;但只有一個「作家」線程。

如果我正確地讀你的問題,那正是你所要求的。另一方面,退一步說出你在這裏試圖解決的問題也許是明智的。

特別是考慮到上述鎖與Java8很好地協作,但在早期版本的Java中看到了問題。

0

也許是這樣的:

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(); 
     } 
    } 
}