You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

删除作为Monitor的对象后锁是否会移除?并发场景下同步状态如何?

全局Map中移除同步对象后的并发影响分析

问题场景

假设存在一个全局公共Map,其中存储的对象被用作其他类方法中synchronized代码块的监视器(Monitor)。当我们从Map中移除这些对象,且垃圾回收器(GC)将它们从应用内存中清除时,会发生什么?

示例代码

LockTable类

public final class LockTable {
    public static final Map<String, Object> lockers = new HashMap<>();
}

FirstClass类

public class FirstClass {
    public void methodWithRemovingKey() throws InterruptedException {
        String someKey = "someKey";

        new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {}

            System.out.println("Removing key " + someKey);
            LockTable.lockers.remove(someKey);
        }).start();

        new SecondClass().methodWithSynchronizedBlock(someKey);
    }

    public static void main(String[] args) throws InterruptedException {
        new FirstClass().methodWithRemovingKey();
    }
}

SecondClass类

public class SecondClass {
    public void methodWithSynchronizedBlock(String key) throws InterruptedException {
        System.out.println("Entered methodWithSynchronizedBlock");

        synchronized (LockTable.lockers.computeIfAbsent(key, k-> new Object())) {
            System.out.println("Synchronized object is used " + LockTable.lockers.get(key));
            Thread.sleep(10000);
            System.out.println("Synchronized object was used " + LockTable.lockers.get(key));
        }

        System.out.println("Exit methodWithSynchronizedBlock");
    }
}

程序输出

Entered methodWithSynchronizedBlock
Synchronized object is used java.lang.Object@96532d6
Removing key someKey
Synchronized object was used null
Exit methodWithSynchronizedBlock

核心问题

在并发环境下出现该场景时,同步机制会受到何种影响?对应的锁是否会被移除?


解答

核心结论:同步机制不会失效,当前持有的锁也不会被移除

  • synchronized锁定的是对象实例本身,而非Map中的引用。线程进入同步块时,已经通过computeIfAbsent获取到了具体的Object实例,此时锁就绑定在这个实例上。即便后续Map移除了该对象的引用,线程持有的锁依然有效,直到同步块执行完毕才会释放。
  • 同步块执行期间,线程本身持有该对象的引用,GC不会回收这个对象——只有当同步块执行完毕、线程释放锁,且没有其他引用指向该对象时,GC才会将其回收。从输出也能看到,移除Map键后,同步块依然正常执行到结束,说明锁全程有效。

并发场景下的风险

  • 锁复用失效:如果后续有其他线程用同一个key调用computeIfAbsent,会创建新的Object实例作为锁。这会导致不同线程针对同一个key使用不同的锁,完全失去互斥效果,引发并发安全问题(比如多个线程同时进入本应互斥的代码块)。
  • 竞态条件:如果移除操作和computeIfAbsent操作没有额外同步,可能出现竞态:比如线程A在执行computeIfAbsent时,线程B刚好移除了key,导致线程A创建新对象;后续线程C用同一个key又拿到另一个新对象,锁逻辑完全混乱。

内容的提问来源于stack exchange,提问作者Alexander Volkov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 14:07:08