【问题标题】:Spring Singleton Update SetSpring Singleton 更新集
【发布时间】:2019-12-30 10:49:28
【问题描述】:

我知道 Spring Singleton 不是 thread-safe。但我不知道 Spring Singleton 如何与 Set 一起使用。我们有一个 Singleton Scope 的 Spring 服务。该服务使用Set<String> 来保留一些价值。

@Bean
@Scope("singleton")
public class TestSetInSpringSingleton{
private Set<String> variableAddeds = new HashSet<>();
public void increment(String variableAdded) {
        variableAddeds.add(variableAdded);
    }
}

Set&lt;String&gt; variableAddeds 是否运作良好,它保留了所有请求增量中的所有值(不是关于 List 和 Set 之间区别的问题)?或者当有很多请求同时出现时是否会丢失任何价值?

对不起,如果我的问题不够清楚。
这是一个例子。
有2个请求R1、R2同时调用这个服务。
R1 将“value1”添加到 Set。
R2 将“value2”添加到 Set。
据我了解,R1 和 R2 将从缓存中获取实例 TestSetInSpringSingleton 的副本。想象一下,当 R2 得到一个实例的副本时,R1 还没有完成他的增量(所以 Set variableAddeds 仍然是空的)。

  1. R1、R2 完成后 Set variableAddeds 的值是多少?
    variableAddeds = {"value1", "value2"} 或 variableAddeds = {"value2"} (因为 R2 获取实例副本的那一刻,R1 没有完成)?

  2. 我不认为使用 ConcurrenceHashmap 是好的解决方案,因为每个服务都使用增量一次的方法,所以没有并发访问。在方法增量处使用同步可能是一个很好的解决方案?

谢谢!

【问题讨论】:

    标签: java spring scope singleton


    【解决方案1】:

    来自 HashSet 的 Java Doc:请注意,此实现是不同步的。如果多个线程同时访问一个哈希集,并且至少有一个线程修改了该集,则必须对外同步

    您的函数increment(string variableAdded) 在被多个线程访问时几乎可能会抛出ConcurrentModificationException

    您可以将您的公共increment(String variableAdded) 移动到如下同步函数:

    public synchronized void increment(String variableAdded) {
            variableAddeds.add(variableAdded);
        }
    }
    
    

    或者您可以改为使用并发哈希图集

    Set<String> variableAddeds = ConcurrentHashMap.newKeySet();
    

    【讨论】:

      【解决方案2】:

      按照@ZhongYu 的建议使用Concurrent Set

      private Set<String> variableAddeds = ConcurrentHashMap.newKeySet();
      

      类似于HashSet,但同时使用也安全

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多