Java同步问题 - 聊天多个聊天室应用程序

时间:2011-09-02 08:23:00

标签: java synchronization synchronized livechat chatroom

我正在开发一个聊天应用程序。我有一个处理聊天消息的功能。每个聊天室都由唯一的短代码标识。现在我希望当正在处理一个短代码的消息时,应该等待同一短代码的另一条消息,而其他短代码的消息应该继续。

请考虑遵循代码的和平,它有什么问题,因为同一短代码的消息正在并行处理。我只是猜不出问题

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 + " ......");
    }
}

2 个答案:

答案 0 :(得分:4)

我能看到的第一个原因就在这里

Object lock = null;

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

这个代码块在任何互斥锁之外执行,所以几个线程可以同时运行它,所以每个线程(具有相同的短代码)得到它自己的锁,彼此独立(和只有其中一个将存储在锁定hashmap中 - 这是一个问题,因为普通的HashMap不是为并发使用而设计的 - 你无法准确地预测哪个“put”将按照哪个顺序生效,你甚至可以得到此代码中的异常或错误行为,如果当前put导致调整大小,例如)。由于每个线程都获得了自己的锁,因此它不会阻止它与其他线程并发获取它,从而获得另一个锁。

最简单(但不是非常有效)的解决方法:

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 + " ......");
    }
}

这样,每个短代码只能获得一个锁。更有效的方法是使用Guava lib中的ComputableConcurrentHashMap。

答案 1 :(得分:1)

同步机制很好,但是你可能想看看java.util.concurrent.locks包中的Lock接口。这些使用起来比较冗长,但允许更大的灵活性,因为它可以执行尝试和失败之类的操作,或尝试通过超时获取。