2011-10-19 4 views
0

私は、ユーザーがソケットを使っていろいろな場所から一度にログインする単純な銀行シミュレータをコーディングしています。銀行サーバーでは、すべての着信リクエストを格納するための有界バッファーを保持しています(例:資金の振り替え、口座残高の取得など)、この要求キューから各要求を引き出すためにバックグラウンドスレッドがサーバーエンド(バッファーリーダー) OSのスレッドスケジューラとして)、FCFSベースで実装されています。バウンドバッファ(プロデューサ/コンシューマ)を使用すると、同期メソッド/デッドロックの苦労を回避できますか?

バッファのput()メソッドとget()メソッドを条件付き同期にしました。

例:

// put method 
while(total_buffer_size == current_total_requests) { 

System.out.println("Buffer is full"); 
wait(); 

} 

だから私の質問は、は、我々はデータの破損を避けるためには、Get-バランスまたは転送ファンドのようなメソッドを同期させることがありますか?私は、バッファリーダーが各リクエストを1つずつと関連するアクションを取るので、それは必要ではないと信じています。 これでデッドロックの状況を回避しましたか??どう思いますか?おかげ

EDIT2:

public synchronized boolean put(Messenger msg, Thread t, Socket s) throws InterruptedException { 
     while(total_buffer_size == current_total_requests) { 

      System.out.println("Buffer is full"); 
      wait(); 

     } 
     current_total_requests++; 

     requests[cur_req_in] = new Request(msg, s); // insert into Queue 

     cur_req_in = (cur_req_in + 1) % total_buffer_size ; 

     notifyAll(); 

     return true; 
    } 

    // take each incoming message in queue. FIFO rule followed 
    public synchronized Request get() throws InterruptedException { 

      while(current_total_requests==0) wait(); 
      Request out = requests[cur_req_out]; 
      requests[cur_req_out] = null; 

      cur_req_out = (cur_req_out + 1) % total_buffer_size ; 
      current_total_requests--; 
      notifyAll(); //wake all waiting threads to continue put() 
      return out; 

    } 
+1

一度に1つのアクションしか実行しないので、同期する必要はありません。しかし、これは全体的なパフォーマンスを著しく阻害する可能性があります。なぜなら、千のリクエストを受け取った場合、各リクエストを処理するのに4msかかるため、キューの最後の人はサーバからの応答を得るのに4秒ほど待たなければならないからです。それは長い時間!! – vishakvkt

+0

+1をすばやく返信します。これは、パフォーマンスがあまり考慮されていない学術プロジェクトのためのものです。私は何とかデッドロックの状況がないことを証明する必要があります。ありがとうございました – coder9

答えて

1

1つしかない場合、消費者(「バッファ」からの要求を消費つのスレッドはすなわち)、あなたはに関連する方法上の任意の同期を使用する必要はありません銀行口座。しかし、私はあなたの現在の "有界バッファ"の実装が有効であるとは思わない。具体的には:多くのスレッドがwhileループを過ぎて取得する方法を絶対に保証はありません

while(total_buffer_size == current_total_requests) { 

System.out.println("Buffer is full"); 
wait(); 

} 

current_total_requestsがインクリメントされる直前にコンテキストスイッチを実行すると、バッファサイズ許可されているものよりも多くの要求をキュー。 putメソッドが同期化されていない限り、このアプローチは非常に信頼性が低く、競合状態になりがちです。

制限付きバッファを使用する場合は、Javaの既存の「制限付きバッファ」または具体的にはBlockingQueueのいずれかを使用します。 put(...)BlockingQueueブロック:このキューに

挿入し、指定された要素、スペースのために利用可能になるために必要に応じて待っています。

キューにデータがない場合は、take()にもブロックされます。私はあなたが同時性ライブラリの項目の1つを使用できるかどうかわかりませんが、できない場合はBoundedBufferを修正する必要があります。

+0

[引用] 1つのコンシューマ(つまり、 "バッファ"からのリクエストを消費するスレッド)が1つだけの場合、銀行口座に関連する方法では同期を使用する必要はありません。 1つのBuffer ReaderスレッドのみがBufferから要求を引き出し、関連するアクションを実行し、要求を送信した各スレッドを確認します。私自身のBounded Bufferを使用する必要があります。 – coder9

+0

@coder、kk、私はちょうどあなたの編集を見て、 'put' /' get'を同期させてからうまくいくように見えます。競争条件に関する私の最初の懸念を無視することができます。ユーザーがサイズ0の有界バッファを作成し、 'put' /' get'を実行しようとした場合のような「コーナー」ケースをチェックする必要があります。サイズ1はどうですか? (私は何が起こるかを見るためにあなたのロジックを通過していないが、それらについて考えることがあります) – Kiril

関連する問題