这个类是线程安全的吗?

时间:2013-08-06 10:08:30

标签: java collections thread-safety getter-setter

这个班是一个单身人士。我不太擅长线程安全。 这个类是线程安全的吗?省略了一些方法,但它们仅用于一个线程。这里列出的方法将同时从多个线程访问。

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;
    }

}

5 个答案:

答案 0 :(得分:5)

在您显示的所有代码中,只有这些是相关部分:

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;
}

方法rankrankSubtractionByCountsPerDay是纯函数,因此根据定义是线程安全的。现在,由于您的setFactorForTermNameMapping不依赖于任何共享状态,而只是写入volatile变量,因此它的操作是原子的。

如果你没有显示的方法只读取地图,并且经过仔细编写只能访问factorForTermName ,那么整个类可能是线程安全的。

答案 1 :(得分:3)

正如所写,我认为该类是线程安全的。

但是,它是线程安全的主要原因是变量factorForOthersfactorForTermName只写。由于没有代码可以读取它们,因此线程不可能在不一致的状态下看到它们。

这当然使这个课程变得毫无用处,并引出了一个明显的结论:这不是你担心的真正的代码。


如果getter(例如)公开factorForOthers,它仍然是线程安全的。 (A double是基元,参考变量是volatile

如果factorForTermName被曝光,那么肯定存在风险,应用程序暂时不会是线程安全的。这取决于是否可以更新暴露的地图。如果可以,则存在重大的线程安全问题。有两种方法可以缓解这种情况:

  • 您可以使用setFactorForTermNameMapping更改HashMap以包裹Collections.unModifiableMap()。如果你的意图是地图应该是只读的,那么这是最好的解决方案。

  • 您可以使用ConcurrentHashMap代替HashMap

答案 2 :(得分:0)

没有。这不是thread安全的。 HashMap不是线程安全的。您可以将Synchronized方法与HashMap一起使用,以在thread中实现相同的HashTable安全功能

答案 3 :(得分:0)

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

答案 4 :(得分:-5)

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