【问题标题】:Synchronizing on local variable在局部变量上同步
【发布时间】:2014-12-16 09:49:28
【问题描述】:

我注意到ConcurrentHashMap's compute and computeIfAbsent methods 中有一个奇怪的结构:

Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
  //...
}

考虑到 JIT 很可能将其视为无操作,在本地对象上进行同步有什么意义?

【问题讨论】:

    标签: java multithreading java-8 synchronized concurrenthashmap


    【解决方案1】:

    在代码获取对象的监视器后,对该对象的引用存储到tab,这是构成ConcurrentHashMap内容的全局可见节点数组:

    Node<K,V> r = new ReservationNode<K,V>();
    synchronized (r) {
        if (casTabAt(tab, i, null, r)) {
    

    此时,在同一个ConcurrentHashMap上执行其他修改方法的其他线程在遍历全局数组时可能会遇到这个不完整的节点,也就是说Node的引用已经逃逸了。

    虽然在构造 ReservationNode 时,新创建的对象不可能发生争用,但在其他方法中,在数组中找到的 Nodes 上同步,可能存在争用正是因为Node

    这就像“优先同步”。创建者在引用尚未转义的点进行同步,因此保证成功,而在引用转义的点,所有其他线程将不得不等待,在他们访问的不太可能(但仍然可能)的事件中正是Node

    【讨论】:

    • 节点可能需要在野外进行一些种族敏感的内务处理,而不仅仅是构建。
    • @ratchet 怪胎:正如类型名称 ReservationNode 所暗示的那样,该节点的存在主要是为了互斥对同一哈希桶的更新。这是computeIfAbsent 的原子性保证所必需的:一旦开始计算,就不允许对同一密钥进行其他更新。
    • @Holger 我也有与同步here 相关的类似问题,我在套接字对象上使用同步,我想看看我是否可以通过其他一些有效的方式完全摆脱同步?想看看你能不能帮忙。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多