这个代码是线程安全的吗? [英] Is this code a thread-safe one?

查看:150
本文介绍了这个代码是线程安全的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要处理一系列客户请求。每个请求都有其特殊类型。首先,我需要初始化该类型的一些数据,之后,我可以开始处理请求。当客户端类型第一次来时,我只是初始化相应的数据。之后,使用该数据处理该类型的所有以下请求。

I want to process a flow of client requests. Each request has its special type. First I need to initialize some data for that type, and after this I can start processing the requests. When the client type comes for the first time, I just initialize the corresponding data. After this all the following requests of that type are processed using that data.

我需要以线程安全的方式这样做。

I need to do this in a thread-safe manner.

这是我写的代码。它是线程安全的吗?

Here is a code I have written. Is it thread-safe?

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) {}
}

一方面,ConcurrentHashMap不能产生map.put(A,B)== null两次为相同的A.
另一方面,分配和比较操作不是线程安全的。

From one hand, ConcurrentHashMap cannot produce map.put(A,B) == null two times for the same A. From the other hand, the assignment and comparisson operation is not thread-safe.

这段代码是否正确?
如果没有,我该如何解决?

So is this code is ok? If not, how can I fix it?

更新:
我接受了Martin Serrano的答案,因为他的代码是线程安全的,它不容易出现双重初始化问题。但我想注意,我没有找到任何与我的版本,作为一个答案在下面,我的版本不需要同步。

UPDATE: I have accepted the answer of Martin Serrano because his code is thread-safe and it is not prone to double initialization issue. But I would like to note, that I have not found any isssues with my version, posted as an answer below, and my version does not require synchronization.

推荐答案

此代码不是线程安全的,因为

This code is not thread safe because

//already existing index - we already have results and we can use them
processClientUsingClientTypeData(clientTypesInitiated.get(clientTypeIndex));

有机会获得您在put check中临时插入的值。

has a chance of getting the "" value you temporarily insert in the put check.

此代码可以通过线程安装:

This code could be made threadsafe thusly:

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) {}

}

这篇关于这个代码是线程安全的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆