为什么Java的同步集合不使用读/写锁?
在诸如此类的事情之后,当集合同步包装器出现时,我认为同步会得到更有效的处理。现在我研究了代码,我很惊讶它实际上只是用同步块包装集合。Hashtable
Vector
例如,为什么 s 不包括在集合中的同步地图中?是否有一些效率方面的考虑不值得?ReadWriteLock
在诸如此类的事情之后,当集合同步包装器出现时,我认为同步会得到更有效的处理。现在我研究了代码,我很惊讶它实际上只是用同步块包装集合。Hashtable
Vector
例如,为什么 s 不包括在集合中的同步地图中?是否有一些效率方面的考虑不值得?ReadWriteLock
读写锁是性能优化的一部分,这意味着在某些情况下它可以允许更高的并发性。必要的条件是,它们应用于大多数时间读取但未修改的数据结构。
在其他条件下,它们的性能略差于独占锁,这是很自然的,因为它们具有更大的复杂性。
如果读写锁的锁通常保持适度长的时间,并且只对受保护的资源进行少量修改,则此方法效率最高。
因此,读写锁是否优于独占锁取决于用例。最终,您必须通过分析来衡量哪些锁的性能更好。
考虑到这一点,选择一个独占锁来解决一般用例,而不是大多数读者的特殊情况似乎是合适的。Collections.synchronizedMap
更多链接
他们编写了一个工具,该工具可以在适当的情况下自动将Java应用程序中的锁转换为Java应用程序中的锁。出于衡量目的,他们还提供了一些有趣的基准测试结果:ReentrantLocks
ReadWriteLocks
[...]但是,在写入操作更普遍的配置中,具有同步块的版本比基于 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 核机器上速度最快)。
我不认为使用(如果这是你正在谈论的)比使用关键字更快。这两种结构都施加了锁并竖起了记忆障碍,并“以前发生”限制。ReadWriteLock
synchronized
您可能正在谈论做一些聪明的事情,并且为了性能,读取方法被读取锁定,而写入方法被锁定。这可能适用于集合类,但如果对方法进行计数或其他操作,则可能导致用户实现的同步问题 - 即“只读”方法实际上对集合进行了更新。是的,这样做将是一个可怕的想法。Collections.synchronizedMap(...)
java.util
Map
get()
ConcurrentHashmap
被编写为高性能,并直接使用字段而不是块。这使得代码明显更复杂,但也更快。这就是为什么建议将其用于高性能情况的原因。volatile
synchronized
Collections.synchronizedMap(...)
Collections.synchronizedMap(new HashMap<...>())