HashTable是一个线程安全的集合,但是使用ArrayList(它不是线程安全的)初始化它,因为值会危及整个线程安全方面吗?
Hashtable <Employee, ArrayList<Car>> carDealership = new Hashtable<>();
此外,我计划将ArrayLists
中的synchronized
的每个操作都包含在 Collections.synchronizedList(new ArrayList<>())
块中,以防止在使用任何方法操作时出现任何竞争条件。
然而,我还没有将HashTable中的ArrayLists声明为同步列表,这是通过以下代码实现的
ArrayLists
当我将ArrayLists显然添加到HashTable时会发生这种情况。
如何确保HashTable
中的ArrayList
是线程安全的?
是否足以将线程安全的put()
传递给hashTable
的{{1}}方法并且我很高兴?(甚至不担心HashTable
的构造函数?)因此,HashTable的put()
方法甚至无法识别我是否传递了线程安全/不安全的参数?
注意:线程安全是必需的。否则我不会选择这种实施方式。
答案 0 :(得分:2)
确保Hashtable
或ConcurrentHashMap
中的值是线程安全的唯一方法是将其包装起来,以防止任何人添加您无法控制的内容。切勿将Map
本身或其中包含的任何List
公开给代码的其他部分。如果需要,提供获取快照副本的方法,提供向列表添加值的方法,但要确保包装地图的类是创建可以添加到其中的所有列表的类。对地图中“实时”列表的迭代将需要外部同步(如in the JavaDocs of synchronizedList
所述)。
Hashtable
和ConcurrentHashMap
都是线程安全的,因为并发操作不会使它们处于无效状态。这意味着例如如果从具有相同键的两个线程调用put
,则其中一个将返回另一个插入的值作为“旧”值。但是当然你不知道哪一个是第一个,哪个将提前第二个没有一些外部同步。
但是实现完全不同:Hashtable
和Map
返回的同步Collections.synchronizedMap(new HashMap());
类似,因为它们基本上为大多数方法添加了synchronized
修饰符。如果您有大量读取的线程(即锁的高争用),但只是偶尔修改映射,这可能效率低下。 ConcurrentHashMap
提供了更细粒度的锁定:
检索操作(包括get)一般不会阻塞
根据您的使用情况,可以产生明显更好的性能。我还提供了更丰富的API,具有强大的搜索和批量修改操作。
答案 1 :(得分:0)
是的,在这种情况下使用ArrayList
不是线程安全的。您始终可以从表中获取对象并对其进行操作。
CopyOnWriteArrayList
是一个很好的替代品。
但是,当一个线程占用(保存在变量中)集合,另一个线程替换另一个线程时,你仍然会遇到这种情况。
如果您不打算替换表中的列表,那么这不是问题。