简体   繁体   English

该类是线程安全的吗?

[英]Is this class thread-safe?

This class is a singleton. 此类是单身人士。 I'am not very good at thread-safety. 我不太擅长线程安全。 Is this class thread-safe? 该类是线程安全的吗? Some methods are omitted, but they will used only from one thread. 一些方法被省略,但是它们仅在一个线程中使用。 The methods listed here will be accessed from multiple threads simultaneously though. 但是,这里列出的方法将同时从多个线程访问。

public class TermsDto {

    private final static MapSplitter mapSplitter = Splitter
            .on(',').trimResults().omitEmptyStrings()
            .withKeyValueSeparator(":");

    private volatile double factorForOthers = 4;

    private volatile Map<String, Double> factorForTermName = 
            new HashMap<String, Double>();

    public void setFactorForOthers(double factorForOthers) {
        this.factorForOthers = factorForOthers;
    }

    public void setFactorForTermNameMapping(String mapping) {
        HashMap<String, Double> tempFactorForTermName = 
                new HashMap<String, Double>();
        for (Map.Entry<String, String> entry : 
                 mapSplitter.split(mapping).entrySet()) {
            double factor = Double.parseDouble(entry.getValue());
            tempFactorForTermName.put(entry.getKey(), factor);
        }
        factorForTermName = tempFactorForTermName;
    }

}

Of all the code you have shown, only these are relevant parts: 在显示的所有代码中,只有以下几部分是相关的:

private volatile double factorForOthers = 4;

private volatile Map<String, Double> factorForTermName = 
        new HashMap<String, Double>();

public void setFactorForOthers(double factorForOthers) {
    this.factorForOthers = factorForOthers;
}

public void setFactorForTermNameMapping(String mapping) {
    HashMap<String, Double> tempFactorForTermName = 
            new HashMap<String, Double>();
    for (Map.Entry<String, String> entry : 
             mapSplitter.split(mapping).entrySet()) {
        double factor = Double.parseDouble(entry.getValue());
        tempFactorForTermName.put(entry.getKey(), factor);
    }
    factorForTermName = tempFactorForTermName;
}

The methods rank and rankSubtractionByCountsPerDay are pure functions, so are thread-safe by definition. rankrankSubtractionByCountsPerDay方法是纯函数,因此按定义是线程安全的。 Now, since your setFactorForTermNameMapping doesn't depend on any shared state, but only writes to a volatile variable, its operation is atomic. 现在,由于您的setFactorForTermNameMapping不依赖于任何共享状态,而是仅写入volatile变量,因此其操作是原子的。

If the methods you haven't shown only read the map, and are carefully written to access the factorForTermName only once , then the whole class is probably thread-safe. 如果未显示的方法仅读取映射,并且经过精心编写只能访问一次 factorForTermName ,则整个类可能是线程安全的。

As written, I think the class is thread-safe. 如所写,我认为该类是线程安全的。

However, the primary reason that it is thread-safe is that the variables factorForOthers and factorForTermName are write only . 但是,它是线程安全的主要原因是变量factorForOthersfactorForTermName只写的 Since there is no code to read them, there is no possibility that a thread can see them in an inconsistent state. 由于没有代码读取它们,因此线程不可能看到它们处于不一致状态。

This of course makes this class singularly useless, and leads us to the obvious conclusion that this is not the real code you are worried about. 当然,这使该类毫无用处,并且使我们得出明显的结论,那就是这不是您担心的真正代码。


If factorForOthers was exposed by a getter (for example), it would still be thread-safe. 如果factorForOthers被吸气剂暴露(例如),它将仍然是线程安全的。 (A double is a primitive, and the reference variable is volatile double是原始数,参考变量是volatile

If factorForTermName was exposed then there is definitely a risk that the application as a while will not be thread-safe. 如果暴露了factorForTermName ,那么肯定存在应用程序暂时不是线程安全的风险 It depends on whether the exposed map can be updated. 这取决于是否可以更新暴露的地图。 If it can be, then there is a significant thread-safety issue. 如果可以,则存在严重的线程安全问题。 There are two ways to mitigate that: 有两种方法可以减轻这种情况:

  • You could change setFactorForTermNameMapping to wrap the HashMap using Collections.unModifiableMap() . 您可以使用Collections.unModifiableMap()更改setFactorForTermNameMapping以包装HashMap If your intent is that the map should be read-only, then this is the best solution. 如果您的意图是地图应该是只读的,那么这是最好的解决方案。

  • You could use ConcurrentHashMap instead of HashMap . 您可以使用ConcurrentHashMap代替HashMap

No. This isn't thread safe. 不。这不是thread安全的。 HashMap not thread safe as it is. HashMap本身不是线程安全的。 You can use Synchronized method with HashMap to achieve same thread safe functionality in HashTable 您可以将Synchronized方法与HashMap一起使用,以在HashTable实现相同的thread安全功能

假设没有其他方法修改factorForTermName映射,则该类是线程安全的。

否。方法setFactorForTermNameMapping()遍历一个数据结构,该数据结构本身对于遍历可能不是线程安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM