JIT会优化此代码吗?是否需要同步?

| 下面是一个类,其中包含拼写正确的术语的拼写错误地图。石英作业通过调用updateCache()定期更新地图。方法updatecache处理输入映射中的键和值,并将它们存储在临时映射对象中。处理完成后(在for循环之后),它将临时映射分配给本地类变量misspelledToCorrectlySpelled。
package com.test;
导入java.util.HashMap; 导入java.util.Map; 导入org.checkthread.annotations.ThreadSafe; @ThreadSafe 公共类SpellCorrectListCacheManager {
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;
}
} 问题1:JIT优化会优化此代码吗? 实际代码
/*
     * since tempMap is assigned to misspelledToCorrectlySpelled and not
     * used anywhere else, will JIT remove tempMap as shown in the optimized
     * version below?
     */
    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);
    }

    this.misspelledToCorrectlySpelled = 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);
    }
问题2:假设JIT无法优化代码,方法getMisspelledToCorrectlySpelled是否应该同步?
/*
     * 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;
}
    
已邀请:
您应该使用AtomicReference来存储新地图,以避免同步和可见性问题。但是代码中最大的问题是您可以访问一个非线程安全的可变映射到多个线程。您应该将地图包装成不可修改的地图:
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();
}
要回答有关JIT优化的问题:不,JIT不会删除临时映射的用法。     
需要同步的地方需要同步。除了可以遵循JIT和Java内存模型的兼容实现,而且将遵守使用这些规则设计的代码之外,不能假设有关JIT的任何事情。 (有多种同步方法,并非都使用
synchronized
关键字。) 此处要求进行同步,除非“可以”看到陈旧的版本。 (这里可能不是这种情况,它可能是一个非常陈旧的版本,其中包含缓存和所有内容-因此不要打赌!)。只要“部分写入”不会发生,“引用的分配”本身就是原子的,但是不能保证在所有线程上都“立即”传播(“可见”)。 快乐的编码。     

要回复问题请先登录注册