Java 哈希表、ConcurrentHashMap和数据可见性
问题: 我有一个ViewModel基类,它有一个HashMap来存储ViewModel的属性值。然而,我遇到了一个间歇性错误,从这个集合(在一个单独的线程上)读取的数据在添加一个项目后直接返回nullJava 哈希表、ConcurrentHashMap和数据可见性,java,multithreading,concurrency,hashmap,Java,Multithreading,Concurrency,Hashmap,问题: 我有一个ViewModel基类,它有一个HashMap来存储ViewModel的属性值。然而,我遇到了一个间歇性错误,从这个集合(在一个单独的线程上)读取的数据在添加一个项目后直接返回null private HashMap<String, Serializable> _propertyValues = new HashMap<String, Serializable>(); private HashMap_propertyvalue=new HashMap()
private HashMap<String, Serializable> _propertyValues = new HashMap<String, Serializable>();
private HashMap_propertyvalue=new HashMap();
示例:我想在向ViewModel提供用户id时获取用户信息
ViewModel连接到用户ID的PropertyChanged。属性更改处理程序创建后台线程以提取值。后台线程读取用户ID,然后从服务器获取
我们看到的是,在一些罕见的情况下,后台线程直接在提供值(线程1)之后从属性hashmap(线程2)读取null
我的想法:我怀疑这是由于没有线程安全的集合。在回顾线程安全选项时,我遇到了:
TreyConcurrentHashMap就可以了。它有内部同步来防止这些问题。它还有其他一些您可能会觉得有用的方法,例如
putIfAbsent
它相对于
集合的主要缺点。synchronizedMap
的内存占用较大。您还可以使用锁,以便在放弃写锁之前其他进程无法访问信息。锁可能是您唯一的选择。在您的案例中,似乎发生了这样的情况:假设值已被写入,但实际上读取线程在写入线程之前被调用,因此值为null。您需要一个锁,以确保在读线程访问该值之前,写线程已经完成。您所说的“特别注意如何使用它”是什么意思?synchronizedMap(new HashMap())
的优点是HashMap
在过去十年中得到了发展,而Hashtable
却没有。您的另一个选择可能是使用Executors.newSingleThreadExecutor()
类似于队列
。这样,一次只执行一个线程,如果读线程在写线程之后提交,则可以保证读线程已经完成。但这可能会导致性能下降。使用它的两种“不正确”方式是直接访问包装映射(明显的违规行为)和在没有同步的情况下对其执行任何类型的迭代(与Hashtable共享的陷阱)。这就是为什么我认为相比之下,Hashtable
没有什么可以提供的。+1CHM
的一个重要且独特的优点是迭代器的一致性。