2012-07-17 35 views
0
// multiple server instances (replicas), coordinated using MsgCoordinationService 
public class Server { 

    ConcurrentHashMap<TxID,Future<Msg>> local_registry = new ... 
    MsgCoordinationService coordination_service = new .. 

    ... 

    // Socket instance to communicate with a client... 
    public void accept(Socket s) { 
     new Thread(new Worker(s)).start(); 
    } 

    // propose msg to coordination service, register demand to respond to client in local registry 
    public Future<Msg> register(Msg m) { 
     FutureMsg f = new MsgFuture(); // Future handle w. reference to an empty Msg object [= response] 
     TxID uniqueID = coordination_service.propose(s); // transaction ID 
     local_registry.add(uniqueID, f); 
     return f; 
    } 

    // called by coordination service, guaranteeing a global order on msg deliveries 
    public synchronized void deliver(TxID id, Msg m) { 
     ... process Msg object [request] 
     ... if local_registry.contains(id), 'compile' response 
      (using the Msg object from FutureMsg f, f.get() - f.isDone() when a certain Msg flag has been set) 

     ___ now: 
     ... notify waiting 'Worker' threads to check whether their 'Future' object isDone() 
    } 

    private class Worker implements Runnable { 
     ... 
     public void run() { 
      ... 
      Future<Msg> f = Server.this.register(request); // obtained through Socket s 

      while(!f.isDone()) 
       wait(); 

      response = f.get(); 
      ... 
     } 
    } 
} 

我正在實施複製服務[多個服務器,客戶端通信w。一個服務器實例,創建/更新/刪除操作將通過協調服務的方式進行分配,以確保全球消息傳送順序]。分層死鎖(有依賴關係),...或者:如何獲得我的「等待」,「通知」和設計是否正確?

一旦客戶端建立到服務器實例的新連接,所有通信都將通過專用的Worker實例[本地處理讀取請求,並使用Server.this.register(...)廣播C/U/D操作]。

register本身基本上記錄了未來本地處理/回覆的請求 - 並將Msg對象轉發給協調服務。

服務通過deliver ...重新提供Msg對象,並且在處理封裝的任務之後,應該通知最初接收到客戶端請求的實例,以交付相應的響應。

由於某些原因,我的設計似乎被打破... - 沒有synchronized(this) [在Worker#run()],wait()不會等待;與synchronized(this)notifyAll()Server#deliver(...)將不會釋放「阻止」Worker實例上的鎖定。 (a):瞭解wait/notify/notifyAll的基本知識或(b):改進我的設計...或(c):(()):(a)(b)。

回答

2

調用wait/notify的線程需要對調用這些方法的對象進行鎖定,否則會得到異常。在一般形式,假設任意對象:

final Object obj = new Object(); 
... 

synchronized(obj) { 
    while(/* condition */) { 
     obj.wait(); 
    } 
} 

之所以你wait沒有被該notify公佈的是,你正在做一個this.wait()不同的對象不是一個裏面,你在呼喚notify,因此他們沒有配對。您需要爲兩個呼叫使用相同的實例。您在Worker的實例中執行this.wait(),並在Server的實例中執行this.notifyAll(),因此this不引用相同的對象。

您應該創建一個跨類和線程可見的同步對象,並在該對象上進行同步。

相關問題