sti*_*kj1 5 java multithreading
我正在尝试实现线程安全的Map缓存,并且希望对缓存Strings进行延迟初始化。这是我实现的第一步:
public class ExampleClass {
private static final Map<String, String> CACHED_STRINGS = new HashMap<String, String>();
public String getText(String key) {
String string = CACHED_STRINGS.get(key);
if (string == null) {
synchronized (CACHED_STRINGS) {
string = CACHED_STRINGS.get(key);
if (string == null) {
string = createString();
CACHED_STRINGS.put(key, string);
}
}
}
return string;
}
}
Run Code Online (Sandbox Code Playgroud)
编写完这段代码后,Netbeans就“双重检查锁定”警告了我,因此我开始对其进行研究。我找到了“双重检查锁定已损坏”声明并已阅读,但我不确定我的实现是否会受到它提到的问题的影响。看来本文中提到的所有问题都与new在synchronized块中使用运算符进行对象实例化有关。我没有使用new运算符,并且字符串是不可变的,因此我不确定本文是否与这种情况相关。这是在字符串中缓存字符串的线程安全方法HashMap吗?线程安全性是否取决于createString()方法中采取的措施?
不,这是不正确的,因为第一次访问是在同步块之外完成的。
这在某种程度上取决于如何实施get和put可能实施。您必须牢记它们不是原子操作。
例如,如果它们是这样实现的:
public T get(string key){
Entry e = findEntry(key);
return e.value;
}
public void put(string key, string value){
Entry e = addNewEntry(key);
//danger for get while in-between these lines
e.value = value;
}
private Entry addNewEntry(key){
Entry entry = new Entry(key, ""); //a new entry starts with empty string not null!
addToBuckets(entry); //now it's findable by get
return entry;
}
Run Code Online (Sandbox Code Playgroud)
现在当操作仍在进行中时get可能不会返回,并且整个方法可能返回错误的值。nullputgetText
该示例有点复杂,但您可以看到代码的正确行为依赖于地图类的内部工作。这不好。
虽然您可以查看该代码,但您无法考虑编译器、JIT 和处理器优化以及内联,这些优化和内联可以有效地改变操作顺序,就像我选择编写该映射实现的古怪但正确的方式一样。
| 归档时间: |
|
| 查看次数: |
443 次 |
| 最近记录: |