0

I know that Spring Singleton is not thread-safe. But I don't know how Spring Singleton works with Set. We have a Spring service with Singleton Scope. This service uses a Set<String> to keep some value.

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

Does the Set<String> variableAddeds work well, it keeps all value from all of the request increment (not a question about the difference between List and Set)? Or is there any value lost when there is a lot of requests come at the same time?

Sorry if my question is not clear enough.
This is an exemple.
There are 2 requests R1, R2 who call this service at the same time.
R1 add "value1" to the Set.
R2 add "value2" to the Set.
As i understand, R1 and R2 will get a copy of instance TestSetInSpringSingleton from cache. Imagine at the time R2 get a copy of instance, R1 has not finished his increment (so the Set variableAddeds is still empty).

  1. What is the value of Set variableAddeds after that R1, R2 finish ?
    variableAddeds = {"value1", "value2"} or variableAddeds = {"value2"} (because the moment R2 get a copy of instance, R1 didn't finish) ?

  2. I don't think using ConcurrenceHashmap is good solution because each service use the method increment one time, so there is not concurrence access. Using synchronize at method increment maybe a good solution ?

Thank you !

Blocfos
  • 11
  • 4

2 Answers2

0

From the Java Doc of HashSet: Note that this implementation is not synchronized. If multiple threads access a hash set concurrently, and at least one of the threads modifies the set, it must be synchronized externally

Your function increment(string variableAdded) will almost likely throw a ConcurrentModificationException while being accessed by multiple threads.

You can either move your public increment(String variableAdded) to a synchronized function like below:

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

Or You can instead use a concurrent hashmap set

Set<String> variableAddeds = ConcurrentHashMap.newKeySet();
papaya
  • 1,505
  • 1
  • 13
  • 26
0

Use a Concurrent Set as @ZhongYu suggest

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

similar to HashSet, but also safe to use concurrently

Ori Marko
  • 56,308
  • 23
  • 131
  • 233