假设我有一个注册到服务器的客户端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对程序员解决同步问题有多大帮助。
发布于 2015-06-11 17:50:26
不,如果类是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关键字
发布于 2015-06-11 17:34:50
如果您使用的是Java 8,您可以使用以下代码进行检查:
registeredClients.computeIfAbsent(client, c -> {throw new UnknownClientException();});检查键是否存在和lambda的执行是原子的。这要求UnknownClientException是一个未检查的异常。
对于Java7,我没有这么简单的解决方案。
https://stackoverflow.com/questions/30776176
复制相似问题