假设我有一个ConcurrentHashMap客户端注册到服务器(在Server类中):

Map<ClientID, String> registeredClients = new ConcurrentHashMap<ClientID, String>();


在我的注册方法中(在Server类中),我有:

  public void synchronized register(ClientID client, String clientName) {
        if(!registeredClients.containsKey(client))
          registeredClients.put(client, clientName);
  }


在服务器的任何其他方法中,我总是在开始时检查客户端是否已注册(以确保他有资格使用该方法):

if(!registeredClients.containsKey(client))
  throw new UnknownClientException();


每个客户端有一个服务器线程。

我是否需要将该支票与类似内容同步?

synchronized(registeredClients) {
  if(!registeredClients.containsKey(client))
    throw new UnknownClientException();
}


我认为应该这样做,因为从理论上讲,客户端可以在通过if防护之后并引发异常之前注册(使异常实际上是错误的)。

我不太了解ConcurrentHashMap可以帮助程序员解决同步问题。

最佳答案

不,如果Class为ConcurrentHashMap,则不必同步containsKey api,因为如documentation中所述,其操作是线程安全的(您可以阅读所有文档,以了解如何管理并发访问)。

我建议您进行两个修改:

更改

Map<ClientID, String> registeredClients = new ConcurrentHashMap<ClientID, String>();



ConcurrentMap<ClientID, String> registeredClients = new ConcurrentHashMap<ClientID, String>();

因为您要在代码中显式管理并发访问

完成1.后,您可以使用registeredClients.putifAbsent(client, clientName);

代替

  if(!registeredClients.containsKey(client))
          registeredClients.put(client, clientName);


并避免在方法签名中使用synchronized关键字

关于java - Java ConcurrentHashMap和同步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30776176/

10-11 19:53