同步块中 HashMap 元素的可见性

Visibility of HashMap elements in synchronized block

提问人:Роман Григорьев 提问时间:7/24/2023 更新时间:7/24/2023 访问量:55

问:

我研究了很多次,以找出我问题的答案。 在春季,我们有这个班级 https://github.com/spring-projects/spring-framework/blob/b595dc1dfad9db534ca7b9e8f46bb9926b88ab5a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java

我有一个关于singletonFactories字段(第81行)及其用法的问题。

  1. 为什么此字段的类型为 HashMap,而不是例如 ConcurrentHashMap?线程安全吗?

我想是因为这个字段只在同步块中使用始终相同的监视器对象(this.singletonObjects),并且退出同步块后的更改将在具有相同监视器的块输入处对其他人可见。 我的第二个问题是:2.singletonFactories(put 操作)的所有更改都会对其他线程可见吗? 线程 2 是否会在几千年前看到线程 1 增加的新值?HashMap 中的数组不是可失性的。

是的,我们在 this.singletonObjects 上有同步,但它仅适用于为 singletonFactories 字段分配新值,不是吗?还是在出口处刷新字段意味着所有嵌入字段也刷新到主内存中?所有线程都将在 singletonFactories 上看到实际引用,但我不确定在退出同步块后是否可以看到 singletonFactories 的更改(将新对象放入映射)。

我想这是线程安全的,但我想知道更多。

谢谢你的帮助!!

我希望线程安全行为,但我不确定我是否很好地理解它。

Java Spring 多线程 哈希图 同步

评论

0赞 tgdavies 7/24/2023
这回答了你的问题吗?同步的关键字是否解决了可见性问题?

答:

0赞 dan1st 7/24/2023 #1

HashMap不是线程安全的,但仅在 -blocks 中使用。singletonFactoriessynchronized

如果我们看一下访问它的方法之一,我们可以看到:

//code from https://github.com/spring-projects/spring-framework/blob/b595dc1dfad9db534ca7b9e8f46bb9926b88ab5a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java#L137-L144
//licensed under Apache 2
//comments have been added
protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {//synchronized here
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);//access inside synchronized block
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }

由于 的所有用途都使用 (-blocks) 的内在锁进行保护,因此即使代码使用 .HashMapsingletonObjectssynchronizedHashMap

它可能以这种方式完成,因为主要用于初始化和/或很少争用,或者由于对象需要一起更改(例如,也许他们希望避免两个方法同时更新它),并且如果有块,则不需要。singletonFactoriessynchronizedConcurrentHashMap

另一方面,现有的 Spring Bean 可能经常被读取/从不同的线程读取,因此访问它们可能会有更高的争用,从而导致需要。ConcurrentHashMap

请注意,我不是 Spring 开发人员/我没有编写此代码。我只是根据我正在阅读的代码做出假设。