我想处理客户请求的流程。每个请求都有其特殊类型。首先,我需要为该类型初始化一些数据,然后,我可以开始处理请求。当客户端类型第一次出现时,我只是初始化相应的数据。之后,将使用该数据处理该类型的所有以下所有请求。
我需要以线程安全的方式执行此操作。
这是我编写的代码。它是线程安全的吗?
public class Test {
private static Map<Integer, Object> clientTypesInitiated = new ConcurrentHashMap<Integer, Object>();
/* to process client request we need to
create corresponding client type data.
on the first signal we create that data,
on the second - we process the request*/
void onClientRequestReceived(int clientTypeIndex) {
if (clientTypesInitiated.put(clientTypeIndex, "") == null) {
//new client type index arrived, this type was never processed
//process data for that client type and put it into the map of types
Object clientTypeData = createClientTypeData(clientTypeIndex);
clientTypesInitiated.put(clientTypeIndex, clientTypeData);
} else {
//already existing index - we already have results and we can use them
processClientUsingClientTypeData(clientTypesInitiated.get(clientTypeIndex));
}
}
Object createClientTypeData(int clientIndex) {return new Object();}
void processClientUsingClientTypeData(Object clientTypeData) {}
}
一方面,对于同一个A,ConcurrentHashMap无法产生map.put(A,B)== null两次。
另一方面,赋值和比较操作不是线程安全的。
那么这段代码可以吗?
如果没有,我该如何解决?
更新:
我接受了Martin Serrano的答案,因为他的代码是线程安全的,并且不容易出现双重初始化问题。但是,我想指出的是,我的版本没有发现任何问题,以下为答案发布,并且我的版本不需要同步。
最佳答案
此代码不是线程安全的,因为
//already existing index - we already have results and we can use them
processClientUsingClientTypeData(clientTypesInitiated.get(clientTypeIndex));
有机会获得您临时插入到放置检查中的“”值。
这样可以使该代码成为线程安全的:
public class Test {
private static Map<Integer, Object> clientTypesInitiated = new ConcurrentHashMap<Integer, Object>();
/* to process client request we need to
create corresponding client type data.
on the first signal we create that data,
on the second - we process the request*/
void onClientRequestReceived(int clientTypeIndex) {
Object clientTypeData = clientTypesInitiated.get(clientTypeIndex);
if (clientTypeData == null) {
synchronized (clientTypesInitiated) {
clientTypeData = clientTypesInitiated.get(clientTypeIndex);
if (clientTypeData == null) {
//new client type index arrived, this type was never processed
//process data for that client type and put it into the map of types
clientTypeData = createClientTypeData(clientTypeIndex);
clientTypesInitiated.put(clientTypeIndex, clientTypeData);
}
}
}
processClientUsingClientTypeData(clientTypeData);
}
Object createClientTypeData(int clientIndex) {return new Object();}
void processClientUsingClientTypeData(Object clientTypeData) {}
}