在这种情况下,易失性hashmap是否足够?

时间:2016-08-21 09:10:04

标签: java multithreading concurrency volatile

我之前写过一段代码,它从jar文件中动态加载类。 因此,基本上可以在123-de目录中存在a.jar,在456-fg目录中存在另一个a.jar。现在,根据某些参数,我决定使用哪个jar,并从123-de目录或456-fg目录加载一个类说calc.java。

为此,我必须创建类加载器并使用这些类加载器来加载calc.java

当然,每个jar应该有一个类加载器,每个类在内存中加载单个类。

为此,我使用了一个存储类加载器/类的并发hashmap。 说这个并发hashmap的关键是目录名。

所以,给定一个目录,我检查是否已经存在类加载器 - 如果不是我在一个上创建然后存储它。

if(classLoaderMap.get(directoryPath) == null){
        rlock.lock();
        try{
            if(classLoaderMap.get(directoryPath) == null){

                ClassLoader classLoader = // Create classLoader here.
                classLoaderMap.put(directoryPath, classLoader);
            }
        }finally{
            rlock.unlock();
        }
    }

此代码经过测试且运行正常。但今天我正在重新审视这段代码,并观察到我并不真正需要concurrenthashmap,因为我使用显式锁定来写入它。我只需要内存可见性,因为我在锁外读它。所以,我真的在想volatile hashmap是否已完成这项工作?我应该还原它(不要因为它已经测试过了)或者如果我保留它可以吗?

2 个答案:

答案 0 :(得分:5)

您是否正在访问其他地方的classLoaderMap以从中读取值?如果是,您还需要在那里使用相同的锁,以确保内存可见性。

volatile在这种情况下无济于事,因为它只会确保变量classLoaderMap的更新对其他线程可见,而不是对其他线程的内容可见地图本身。

我仍然建议在这种情况下使用ConcurrentHashMap,这样就不需要显式锁定,并确保地图的内容的内存可见性。

使用Java 8,使用ConcurrentHashMap

时,代码可以简化得更多
classLoaderMap.computeIfAbsent(directoryPath, (path) -> createClassLoader(path));

答案 1 :(得分:4)

不,使用常规地图是不安全的,因为您需要锁定读取和写入。一种选择是使用grouped = df.groupby('Date').apply(lambda x: x['Value'].cummax() \ .drop_duplicates()) \ .reset_index() print(df[df.index.isin(grouped['level_1'])]) Date Time Value 0 2000-01-01 09:00:00 2 2 2000-01-01 17:00:00 3 3 2000-01-02 09:00:00 2 4 2000-01-02 13:00:00 3 6 2000-01-03 09:00:00 1 9 2000-01-04 09:00:00 3 ,因此您可以支持非独占读取,而写入仍然是读写独占的。另一种选择(可能是更好的选择)是坚持ReadWriteLock并摆脱锁定。至于如何以原子方式更新的问题,只需使用原子ConcurrentHashMap方法:

computeIfAbsent()