0

チャットアプリを開発しています。チャットメッセージを処理する機能があります。各チャットルームは固有のショートコードで識別されます。ここで、あるショートコードのメッセージが処理されているときに、同じショートコードの別のメッセージを待機し、他のショートコードのメッセージを続行する必要があります。

同じショートコードのメッセージが並行して処理されているため、コードの平和に従うことを検討してください。問題は何ですか。私は問題を推測することはできません

private HashMap<String, Object> locks = new HashMap<String, Object>();

public void handleShortCode(String shortcode,String message,String from)
{
    Object lock = null;

    lock = locks.get(shortcode);
    if (lock == null)
    {
        locks.put(shortcode, lock = new Object());
    }

    synchronized (lock)
    {
        System.out.println("Handling shortcode:" + shortcode);
        // processing
        System.out.println("Successfully handled shortcode:" + shortcode + " ......");
    }
}
4

2 に答える 2

4

私が見ることができる最初の理由はここにあります

Object lock = null;

lock = locks.get(shortcode);
if (lock == null)
{
    locks.put(shortcode, lock = new Object());
}

このコードのブロックはミューテックスの外部で実行されるため、複数のスレッドが同時に実行できるため、各スレッド (同じショートコードを持つ)は互いに独立して独自の lock を取得します(そして、そのうちの 1 つだけが locks ハッシュマップに格納されます)。 -- 問題はどれですか。通常の HashMap は同時使用用に設計されていないためです -- どの「put」が実際にどの順序で有効になるかを正確に予測することはできません。現在の場合、このコードで例外や間違った動作が発生することさえありますputs はサイズ変更を引き起こします)。各スレッドは独自のロックを取得するため、他のスレッドと同時に取得して別のロックを取得することを妨げません。

それを修正する最も簡単な(しかしあまり効率的ではない)方法:

private HashMap<String, Object> locks = new HashMap<String, Object>();
private final Object hashmapLock = new Object();
public void handleShortCode(String shortcode,String message,String from)
{
    Object lock = null;
    synchronized(hashmapLock){
      lock = locks.get(shortcode);
      if (lock == null)
      {
          locks.put(shortcode, lock = new Object());
      }
    }
    synchronized (lock)
    {
        System.out.println("Handling shortcode:" + shortcode);
        // processing
        System.out.println("Successfully handled shortcode:" + shortcode + " ......");
    }
}

このようにして、ショートコードごとに正確に 1 つのロックを取得します。より効率的な方法は、Guava lib の ComputableConcurrentHashMap のようなものを使用することです。

于 2011-09-02T08:40:06.303 に答える
1

同期メカニズムは問題ありませんが、java.util.concurrent.locks パッケージの Lock インターフェイスを見たいと思うかもしれません。これらはより冗長に使用できますが、試行して失敗したり、タイムアウトを使用して取得を試行したりできるため、柔軟性が高くなります。

于 2011-09-02T09:05:38.893 に答える