0

这个类是一个单例。我不太擅长线程安全。这个类是线程安全的吗?省略了一些方法,但它们只会在一个线程中使用。不过,此处列出的方法将同时从多个线程访问。

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

}
4

5 回答 5

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 only once,那么整个类可能是线程安全的。

于 2013-08-06T10:34:41.720 回答
3

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

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

这当然使这个类变得异常无用,并导致我们得出一个明显的结论,即这不是您担心的真正代码。


如果factorForOthers被 getter 暴露(例如),它仍然是线程安全的。(Adouble是一个原语,参考变量是volatile

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

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

  • 您可以使用ConcurrentHashMap而不是HashMap.

于 2013-08-06T10:28:11.543 回答
0

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

于 2013-08-06T10:26:52.453 回答
0

不,这thread不安全。HashMap不是线程安全的。您可以使用Synchronizedwith 方法HashMap来实现相同thread的安全功能HashTable

于 2013-08-06T10:11:22.927 回答
-5

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

于 2013-08-06T10:13:40.443 回答