Java JIT会优化这段代码吗?是否需要同步?
下面是一个类,它包含拼写错误的术语到拼写正确的术语的映射。quartz作业通过调用updateCache()定期更新映射。方法updatecache处理输入映射中的键和值,并将它们存储在临时映射对象中。处理完成后(for循环之后),它将临时映射分配给本地类变量misspelledToCorrectlySpelledJava JIT会优化这段代码吗?是否需要同步?,java,thread-safety,jit,Java,Thread Safety,Jit,下面是一个类,它包含拼写错误的术语到拼写正确的术语的映射。quartz作业通过调用updateCache()定期更新映射。方法updatecache处理输入映射中的键和值,并将它们存储在临时映射对象中。处理完成后(for循环之后),它将临时映射分配给本地类变量misspelledToCorrectlySpelled package com.test; 导入java.util.HashMap; 导入java.util.Map 导入org.checkthread.annotations.Threa
package com.test;
导入java.util.HashMap;
导入java.util.Map
导入org.checkthread.annotations.ThreadSafe
@线程安全
公共类拼写更正ListCacheManager{
private Map<String, String> misspelledToCorrectlySpelled =
new HashMap<String, String>(0);
/*
* invoked by a quartz job thread
*/
public void updateCache(Map<String, String> map) {
Map<String, String> tempMap = new HashMap<String, String>(map.size());
for (Map.Entry<String, String> entry : map.entrySet()) {
//process key and values
String key = entry.getKey().toLowerCase();
String value = entry.getValue().toLowerCase();
tempMap.put(key, value);
}
// update local variable
this.misspelledToCorrectlySpelled = tempMap;
}
/*
* Could be invoked by *multiple* threads
*/
public Map<String, String> getMisspelledToCorrectlySpelled() {
return misspelledToCorrectlySpelled;
}
您应该使用存储新映射,以避免出现同步和可见性问题。但代码中最大的问题是,您将对非线程安全的可变映射的访问权限授予多个线程。您应该将映射包装为不可修改的映射:
private AtomicReference<Map<String, String>> misspelledToCorrectlySpelled =
new AtomicReference<Map<String, String>>(Collections.unmodifiableMap(new HashMap<String, String>(0)));
/*
* invoked by a quartz job thread
*/
public void updateCache(Map<String, String> map) {
Map<String, String> tempMap = new HashMap<String, String>(map.size());
for (Map.Entry<String, String> entry : map.entrySet()) {
//process key and values
String key = entry.getKey().toLowerCase();
String value = entry.getValue().toLowerCase();
tempMap.put(key, value);
}
// update local variable
this.misspelledToCorrectlySpelled.set(Collections.unmodifiableMap(tempMap));
}
/*
* Could be invoked by *multiple* threads
*/
public Map<String, String> getMisspelledToCorrectlySpelled() {
return misspelledToCorrectlySpelled.get();
}
private AtomicReference拼写错误到正确拼写=
新的原子引用(Collections.unmodifiableMap(新的HashMap(0));
/*
*由quartz作业线程调用
*/
公共无效更新缓存(映射){
Map tempMap=newhashmap(Map.size());
对于(Map.Entry:Map.entrySet()){
//过程关键和价值观
String key=entry.getKey().toLowerCase();
字符串值=entry.getValue().toLowerCase();
tempMap.put(键、值);
}
//更新局部变量
this.misspelledToCorrectlySpelled.set(Collections.unmodifiableMap(tempMap));
}
/*
*可由*多个*线程调用
*/
公共地图拼写错误到正确拼写(){
返回拼写错误的tocorrectlyspelled.get();
}
回答您关于JIT优化的问题:不,JIT不会删除临时映射的使用。需要同步的地方需要同步。除了兼容的实现将兼容JLS和Java内存模型,并且将遵守使用这些规则。(有多种同步方法,并非所有方法都使用
synchronized
关键字。)
这里需要同步,除非“可以”看到一个过时的版本。(这里可能不是这种情况,它可能是一个非常过时的版本,有缓存和所有东西——因此不值得打赌!)。就不可能发生“部分写入”而言,“引用赋值”本身是原子的,但不能保证(立即)是原子的跨所有线程传播(“可见”)
愉快的编码。谢谢你的评论。我很乐意看到过时的版本-我的假设是最新的版本将在10秒内对所有线程可见。我的假设正确吗?谢谢你的评论。你建议将映射包装成不可修改的映射非常好-我添加了它。如果我的代码是多线程安全的(除了不使用同步时的陈旧/可见性问题)我不想使用AtomicReference或Volatile。您是否看到不使用AtomicReference时存在陈旧问题以外的其他问题?请参阅“清单8.清单7中的优化代码”在本文中,如何确保JIT不会通过删除代码中的tempMap来优化代码?有没有办法检查JIT是否删除了tempMap?
this.misspelledToCorrectlySpelled = new HashMap<String, String>(map.size());
for (Map.Entry<String, String> entry : map.entrySet()) {
//process key and values
String key = entry.getKey().toLowerCase();
String value = entry.getValue().toLowerCase();
this.misspelledToCorrectlySpelled.put(key, value);
}
/*
* is this assignment atomic operation?
*
* Does this needs to be synchronized?
*
* By not synchronizing, the new map may not
* be visible to other threads *immediately* -- this is
* ok since the new map will be visible after a bit of time
*
*/
this.misspelledToCorrectlySpelled = tempMap;
}
private AtomicReference<Map<String, String>> misspelledToCorrectlySpelled =
new AtomicReference<Map<String, String>>(Collections.unmodifiableMap(new HashMap<String, String>(0)));
/*
* invoked by a quartz job thread
*/
public void updateCache(Map<String, String> map) {
Map<String, String> tempMap = new HashMap<String, String>(map.size());
for (Map.Entry<String, String> entry : map.entrySet()) {
//process key and values
String key = entry.getKey().toLowerCase();
String value = entry.getValue().toLowerCase();
tempMap.put(key, value);
}
// update local variable
this.misspelledToCorrectlySpelled.set(Collections.unmodifiableMap(tempMap));
}
/*
* Could be invoked by *multiple* threads
*/
public Map<String, String> getMisspelledToCorrectlySpelled() {
return misspelledToCorrectlySpelled.get();
}