为什么Java的同步集合不使用读/写锁?

2022-09-02 20:49:58

在诸如此类的事情之后,当集合同步包装器出现时,我认为同步会得到更有效的处理。现在我研究了代码,我很惊讶它实际上只是用同步块包装集合。HashtableVector

例如,为什么 s 不包括在集合中的同步地图中?是否有一些效率方面的考虑不值得?ReadWriteLock


答案 1

读写锁是性能优化的一部分,这意味着在某些情况下它可以允许更高的并发性。必要的条件是,它们应用于大多数时间读取但未修改的数据结构。

在其他条件下,它们的性能略差于独占锁,这是很自然的,因为它们具有更大的复杂性。

如果读写锁的锁通常保持适度长的时间,并且只对受保护的资源进行少量修改,则此方法效率最高。

因此,读写锁是否优于独占锁取决于用例。最终,您必须通过分析来衡量哪些锁的性能更好。

考虑到这一点,选择一个独占锁来解决一般用例,而不是大多数读者的特殊情况似乎是合适的。Collections.synchronizedMap

更多链接

enter image description here

[...]但是,在写入操作更普遍的配置中,具有同步块的版本比基于 Sun 1.6.0_07 JVM 的读写锁的版本快 50%(使用 Sun 1.5.0_15 JVM 快 14%)。

在只有 1 个读取器和 1 个写入器的低争用情况下,性能差异不那么极端,并且三种类型的锁中的每一种在至少一个机器/VM 配置上都产生了最快的版本(例如,请注意,ReentrantLocks 在具有 Sun 1.5.0_15 JVM 的 2 核机器上速度最快)。


答案 2

我不认为使用(如果这是你正在谈论的)比使用关键字更快。这两种结构都施加了锁并竖起了记忆障碍,并“以前发生”限制。ReadWriteLocksynchronized

您可能正在谈论做一些聪明的事情,并且为了性能,读取方法被读取锁定,而写入方法被锁定。这可能适用于集合类,但如果对方法进行计数或其他操作,则可能导致用户实现的同步问题 - 即“只读”方法实际上对集合进行了更新。是的,这样做将是一个可怕的想法。Collections.synchronizedMap(...)java.utilMapget()

ConcurrentHashmap被编写为高性能,并直接使用字段而不是块。这使得代码明显更复杂,但也更快。这就是为什么建议将其用于高性能情况的原因。volatilesynchronizedCollections.synchronizedMap(...)Collections.synchronizedMap(new HashMap<...>())