【问题标题】:Java Synchronization problem -- Chatting multiple chatroom applicationsJava同步问题——聊天多个聊天室应用
【发布时间】:2011-09-02 08:22:59
【问题描述】:

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

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

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

【问题讨论】:

    标签: java synchronization synchronized livechat chatroom


    【解决方案1】:

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

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

    这段代码在任何互斥锁之外执行,因此多个线程可以同时运行它,因此每个线程(具有相同的短代码)拥有自己的锁,彼此独立(并且只有其中一个会存储在 locks hashmap 中——这是哪一个的问题,因为普通的 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 + " ......");
        }
    }
    

    这样您就可以为每个简码获得一个锁。更有效的方法是使用 Guava lib 中的 ComputableConcurrentHashMap 之类的东西。

    【讨论】:

    • 谢谢 -- 效率目前不是问题 -- 您的解决方案符合我的目的 -- 再次感谢
    【解决方案2】:

    同步机制很好,但也许你想看看 java.util.concurrent.locks 包中的 Lock 接口。这些使用起来更冗长,但允许更大的灵活性,因为可以执行诸如尝试失败或尝试超时获取等操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-25
      • 2018-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多