Spring singleton beans, maps and multithreadingShould I mark object attributes as volatile if I init them in @PostConstruct in Spring Framework?How do I efficiently iterate over each entry in a Java Map?What is an efficient way to implement a singleton pattern in Java?Sort a Map<Key, Value> by valuesWhat exactly is Spring Framework for?How do servlets work? Instantiation, sessions, shared variables and multithreadingSome questions on java multithreading,What's the difference between @Component, @Repository & @Service annotations in Spring?Spring: @Component versus @BeanWhat in the world are Spring beans?How to configure port for a Spring Boot application

Will a paper be retracted if a flaw in released software code invalidates its central idea?

How do I explain to a team that the project they will work on for six months will 100% fail?

Is The Lion King live action film made in motion capture?

During the Space Shuttle Columbia Disaster of 2003, Why Did The Flight Director Say, "Lock the doors."?

Does this Foo machine halt?

Validation and verification of mathematical models

Ex-contractor published company source code and secrets online

Why is there a need to prevent a racist, sexist, or otherwise bigoted vendor from discriminating who they sell to?

Does the United States guarantee any unique freedoms?

Where to pee in London?

Does it make sense to occupy open space?

How does The Fools Guild make its money?

In Pokémon Go, why does one of my Pikachu have an option to evolve, but another one doesn't?

Decode a variable-length quantity

Generator for parity?

Word or idiom defining something barely functional

Arrange a list in ascending order by deleting list elements

Physics of Guitar frets and sound

How to display a duet in lyrics?

Could one become a successful researcher by writing some really good papers while being outside academia?

Can I call myself an assistant professor without a PhD

How to realistically deal with a shield user?

Why are the inside diameters of some pipe larger than the stated size?

Should I take out a personal loan to pay off credit card debt?



Spring singleton beans, maps and multithreading


Should I mark object attributes as volatile if I init them in @PostConstruct in Spring Framework?How do I efficiently iterate over each entry in a Java Map?What is an efficient way to implement a singleton pattern in Java?Sort a Map<Key, Value> by valuesWhat exactly is Spring Framework for?How do servlets work? Instantiation, sessions, shared variables and multithreadingSome questions on java multithreading,What's the difference between @Component, @Repository & @Service annotations in Spring?Spring: @Component versus @BeanWhat in the world are Spring beans?How to configure port for a Spring Boot application






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








0















Sometimes I used to do things like this:



@Component class MyBean 
private Map<TypeKey, Processor> processors;

@Autowired void setProcessors(List<Processor> processors)
this.processors = processors.stream().....toMap(Processor::getTypeKey, x -> x);


//some more methods reading this.processors



But, strictly speaking, it's buggy code, isn't it?



1) this.processors is not final, nor is its creation synchronized on the same monitor as every access to it. Thus, every thread - and this singleton can be called from arbitrary thread processing user request - may be observing its own value of this.processors which might be null.



2) Even though no writes happen after the Map is initially populated, Javadoc offers no guarantees on which implementation will be used for the Map, so it might be an implementation not ensuring thread safety when the Map structure changes, or even if anything is modified, or at all. And initial population is changes, so it may break thread safety for who knows how long. Collectors even offer the specialized toConcurrentMap() method, to address that problem - so, at a bare minimum, I should have been using it instead.



But even if I use toConcurrentMap() in #2, I will not be able to make my field final, because then I'll not be able to initialize it in a setter. So here are my choices:



a) Initialize and populate the Map in an autowired constructor, which frankly I prefer. But so few teams do that, so what if we abstain from that solution? What other choices exist?



b) Initialize the Map to an empty final ConcurrentHashMap, then populate it in a setter. This is possible, but we'll have to list.forEach() then map.put(). This looks like it's still Java 6; or we could definitely do map.addAll(list....toMap()) but its useless duplication of the Map, even if temporary.



c) Use volatile on the field. Slightly degrades performance without any need, because after some point the field never gets changed.



d) Use synchronized to access the field and read its values. Clearly even worse than (c).



Also, any of those methods will make the reader think that the code actually wants some multithreading reads/writes to the Map, while actually, it's just multithreaded reading.



So, what does a reasonable guru do when they want something like that?



At this point, the best solution seems to be the one with a volatile field, assigned in a setter by using toConcurrentMap. Is there anything better? Or maybe I am just making up problems no one ever actually encountered?










share|improve this question


























  • So, what does reasonable guru do when they want something like that? -- and your answer is : synchronized. After a while and if there's time, someone will probably change that to some sort of efficient locking mechanism like StampedLock or even manual, sequential, unsynchronized population of a ConcurrentHashMap - which is classical and proven ... although maybe not as "beautiful" compared to stream population. Actual software engineers dont care about beauty all the time - readability, maintainability and stability are much more important

    – specializt
    Mar 27 at 7:12







  • 3





    AFAIR (but I can't find any reference), Spring makes sure there is a happens-before, i.e. the injection of the beans happens before their usage. There should be nothing to worry about. And I don't know of any map (and certainly not the HashMap used by Collectors.toMap()), that would by itself decide to change its internal structure when you only read from it. That said, I would indeed favor constructor injection to setter injection.

    – JB Nizet
    Mar 27 at 7:14











  • i completely missed the fact that the question is about setter injection and a spring singleton. Well in that case : Yes, it doesnt actually matter because injection happens only once per singleton bean

    – specializt
    Mar 27 at 7:17











  • "only once" - it's irrelevant, I don't care how many times it happens, I care about whether the results of that are observed by everyone. Even if something happened eons ago, it might be not yet observed by some thread without proper happens-before. JB Nizet's answer says Spring makes sure of that - I heard that as well and I'll try to find specifics on that.

    – Maksim Gumerov
    Mar 27 at 7:43











  • " by itself decide to change its internal structure when you only read from it." - no of course not that, I was trying to explain that while it's being populated it might and will change its structure, and since it's not thread safe, no one can be sure further reading from it will work well. Thread safety does not only mean "in concurrent accesses" but more general - accesses from concurrent threads. Thus volatile.

    – Maksim Gumerov
    Mar 27 at 7:46


















0















Sometimes I used to do things like this:



@Component class MyBean 
private Map<TypeKey, Processor> processors;

@Autowired void setProcessors(List<Processor> processors)
this.processors = processors.stream().....toMap(Processor::getTypeKey, x -> x);


//some more methods reading this.processors



But, strictly speaking, it's buggy code, isn't it?



1) this.processors is not final, nor is its creation synchronized on the same monitor as every access to it. Thus, every thread - and this singleton can be called from arbitrary thread processing user request - may be observing its own value of this.processors which might be null.



2) Even though no writes happen after the Map is initially populated, Javadoc offers no guarantees on which implementation will be used for the Map, so it might be an implementation not ensuring thread safety when the Map structure changes, or even if anything is modified, or at all. And initial population is changes, so it may break thread safety for who knows how long. Collectors even offer the specialized toConcurrentMap() method, to address that problem - so, at a bare minimum, I should have been using it instead.



But even if I use toConcurrentMap() in #2, I will not be able to make my field final, because then I'll not be able to initialize it in a setter. So here are my choices:



a) Initialize and populate the Map in an autowired constructor, which frankly I prefer. But so few teams do that, so what if we abstain from that solution? What other choices exist?



b) Initialize the Map to an empty final ConcurrentHashMap, then populate it in a setter. This is possible, but we'll have to list.forEach() then map.put(). This looks like it's still Java 6; or we could definitely do map.addAll(list....toMap()) but its useless duplication of the Map, even if temporary.



c) Use volatile on the field. Slightly degrades performance without any need, because after some point the field never gets changed.



d) Use synchronized to access the field and read its values. Clearly even worse than (c).



Also, any of those methods will make the reader think that the code actually wants some multithreading reads/writes to the Map, while actually, it's just multithreaded reading.



So, what does a reasonable guru do when they want something like that?



At this point, the best solution seems to be the one with a volatile field, assigned in a setter by using toConcurrentMap. Is there anything better? Or maybe I am just making up problems no one ever actually encountered?










share|improve this question


























  • So, what does reasonable guru do when they want something like that? -- and your answer is : synchronized. After a while and if there's time, someone will probably change that to some sort of efficient locking mechanism like StampedLock or even manual, sequential, unsynchronized population of a ConcurrentHashMap - which is classical and proven ... although maybe not as "beautiful" compared to stream population. Actual software engineers dont care about beauty all the time - readability, maintainability and stability are much more important

    – specializt
    Mar 27 at 7:12







  • 3





    AFAIR (but I can't find any reference), Spring makes sure there is a happens-before, i.e. the injection of the beans happens before their usage. There should be nothing to worry about. And I don't know of any map (and certainly not the HashMap used by Collectors.toMap()), that would by itself decide to change its internal structure when you only read from it. That said, I would indeed favor constructor injection to setter injection.

    – JB Nizet
    Mar 27 at 7:14











  • i completely missed the fact that the question is about setter injection and a spring singleton. Well in that case : Yes, it doesnt actually matter because injection happens only once per singleton bean

    – specializt
    Mar 27 at 7:17











  • "only once" - it's irrelevant, I don't care how many times it happens, I care about whether the results of that are observed by everyone. Even if something happened eons ago, it might be not yet observed by some thread without proper happens-before. JB Nizet's answer says Spring makes sure of that - I heard that as well and I'll try to find specifics on that.

    – Maksim Gumerov
    Mar 27 at 7:43











  • " by itself decide to change its internal structure when you only read from it." - no of course not that, I was trying to explain that while it's being populated it might and will change its structure, and since it's not thread safe, no one can be sure further reading from it will work well. Thread safety does not only mean "in concurrent accesses" but more general - accesses from concurrent threads. Thus volatile.

    – Maksim Gumerov
    Mar 27 at 7:46














0












0








0








Sometimes I used to do things like this:



@Component class MyBean 
private Map<TypeKey, Processor> processors;

@Autowired void setProcessors(List<Processor> processors)
this.processors = processors.stream().....toMap(Processor::getTypeKey, x -> x);


//some more methods reading this.processors



But, strictly speaking, it's buggy code, isn't it?



1) this.processors is not final, nor is its creation synchronized on the same monitor as every access to it. Thus, every thread - and this singleton can be called from arbitrary thread processing user request - may be observing its own value of this.processors which might be null.



2) Even though no writes happen after the Map is initially populated, Javadoc offers no guarantees on which implementation will be used for the Map, so it might be an implementation not ensuring thread safety when the Map structure changes, or even if anything is modified, or at all. And initial population is changes, so it may break thread safety for who knows how long. Collectors even offer the specialized toConcurrentMap() method, to address that problem - so, at a bare minimum, I should have been using it instead.



But even if I use toConcurrentMap() in #2, I will not be able to make my field final, because then I'll not be able to initialize it in a setter. So here are my choices:



a) Initialize and populate the Map in an autowired constructor, which frankly I prefer. But so few teams do that, so what if we abstain from that solution? What other choices exist?



b) Initialize the Map to an empty final ConcurrentHashMap, then populate it in a setter. This is possible, but we'll have to list.forEach() then map.put(). This looks like it's still Java 6; or we could definitely do map.addAll(list....toMap()) but its useless duplication of the Map, even if temporary.



c) Use volatile on the field. Slightly degrades performance without any need, because after some point the field never gets changed.



d) Use synchronized to access the field and read its values. Clearly even worse than (c).



Also, any of those methods will make the reader think that the code actually wants some multithreading reads/writes to the Map, while actually, it's just multithreaded reading.



So, what does a reasonable guru do when they want something like that?



At this point, the best solution seems to be the one with a volatile field, assigned in a setter by using toConcurrentMap. Is there anything better? Or maybe I am just making up problems no one ever actually encountered?










share|improve this question
















Sometimes I used to do things like this:



@Component class MyBean 
private Map<TypeKey, Processor> processors;

@Autowired void setProcessors(List<Processor> processors)
this.processors = processors.stream().....toMap(Processor::getTypeKey, x -> x);


//some more methods reading this.processors



But, strictly speaking, it's buggy code, isn't it?



1) this.processors is not final, nor is its creation synchronized on the same monitor as every access to it. Thus, every thread - and this singleton can be called from arbitrary thread processing user request - may be observing its own value of this.processors which might be null.



2) Even though no writes happen after the Map is initially populated, Javadoc offers no guarantees on which implementation will be used for the Map, so it might be an implementation not ensuring thread safety when the Map structure changes, or even if anything is modified, or at all. And initial population is changes, so it may break thread safety for who knows how long. Collectors even offer the specialized toConcurrentMap() method, to address that problem - so, at a bare minimum, I should have been using it instead.



But even if I use toConcurrentMap() in #2, I will not be able to make my field final, because then I'll not be able to initialize it in a setter. So here are my choices:



a) Initialize and populate the Map in an autowired constructor, which frankly I prefer. But so few teams do that, so what if we abstain from that solution? What other choices exist?



b) Initialize the Map to an empty final ConcurrentHashMap, then populate it in a setter. This is possible, but we'll have to list.forEach() then map.put(). This looks like it's still Java 6; or we could definitely do map.addAll(list....toMap()) but its useless duplication of the Map, even if temporary.



c) Use volatile on the field. Slightly degrades performance without any need, because after some point the field never gets changed.



d) Use synchronized to access the field and read its values. Clearly even worse than (c).



Also, any of those methods will make the reader think that the code actually wants some multithreading reads/writes to the Map, while actually, it's just multithreaded reading.



So, what does a reasonable guru do when they want something like that?



At this point, the best solution seems to be the one with a volatile field, assigned in a setter by using toConcurrentMap. Is there anything better? Or maybe I am just making up problems no one ever actually encountered?







java spring multithreading






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 27 at 7:22









skomisa

7,8064 gold badges26 silver badges48 bronze badges




7,8064 gold badges26 silver badges48 bronze badges










asked Mar 27 at 6:57









Maksim GumerovMaksim Gumerov

3722 silver badges19 bronze badges




3722 silver badges19 bronze badges















  • So, what does reasonable guru do when they want something like that? -- and your answer is : synchronized. After a while and if there's time, someone will probably change that to some sort of efficient locking mechanism like StampedLock or even manual, sequential, unsynchronized population of a ConcurrentHashMap - which is classical and proven ... although maybe not as "beautiful" compared to stream population. Actual software engineers dont care about beauty all the time - readability, maintainability and stability are much more important

    – specializt
    Mar 27 at 7:12







  • 3





    AFAIR (but I can't find any reference), Spring makes sure there is a happens-before, i.e. the injection of the beans happens before their usage. There should be nothing to worry about. And I don't know of any map (and certainly not the HashMap used by Collectors.toMap()), that would by itself decide to change its internal structure when you only read from it. That said, I would indeed favor constructor injection to setter injection.

    – JB Nizet
    Mar 27 at 7:14











  • i completely missed the fact that the question is about setter injection and a spring singleton. Well in that case : Yes, it doesnt actually matter because injection happens only once per singleton bean

    – specializt
    Mar 27 at 7:17











  • "only once" - it's irrelevant, I don't care how many times it happens, I care about whether the results of that are observed by everyone. Even if something happened eons ago, it might be not yet observed by some thread without proper happens-before. JB Nizet's answer says Spring makes sure of that - I heard that as well and I'll try to find specifics on that.

    – Maksim Gumerov
    Mar 27 at 7:43











  • " by itself decide to change its internal structure when you only read from it." - no of course not that, I was trying to explain that while it's being populated it might and will change its structure, and since it's not thread safe, no one can be sure further reading from it will work well. Thread safety does not only mean "in concurrent accesses" but more general - accesses from concurrent threads. Thus volatile.

    – Maksim Gumerov
    Mar 27 at 7:46


















  • So, what does reasonable guru do when they want something like that? -- and your answer is : synchronized. After a while and if there's time, someone will probably change that to some sort of efficient locking mechanism like StampedLock or even manual, sequential, unsynchronized population of a ConcurrentHashMap - which is classical and proven ... although maybe not as "beautiful" compared to stream population. Actual software engineers dont care about beauty all the time - readability, maintainability and stability are much more important

    – specializt
    Mar 27 at 7:12







  • 3





    AFAIR (but I can't find any reference), Spring makes sure there is a happens-before, i.e. the injection of the beans happens before their usage. There should be nothing to worry about. And I don't know of any map (and certainly not the HashMap used by Collectors.toMap()), that would by itself decide to change its internal structure when you only read from it. That said, I would indeed favor constructor injection to setter injection.

    – JB Nizet
    Mar 27 at 7:14











  • i completely missed the fact that the question is about setter injection and a spring singleton. Well in that case : Yes, it doesnt actually matter because injection happens only once per singleton bean

    – specializt
    Mar 27 at 7:17











  • "only once" - it's irrelevant, I don't care how many times it happens, I care about whether the results of that are observed by everyone. Even if something happened eons ago, it might be not yet observed by some thread without proper happens-before. JB Nizet's answer says Spring makes sure of that - I heard that as well and I'll try to find specifics on that.

    – Maksim Gumerov
    Mar 27 at 7:43











  • " by itself decide to change its internal structure when you only read from it." - no of course not that, I was trying to explain that while it's being populated it might and will change its structure, and since it's not thread safe, no one can be sure further reading from it will work well. Thread safety does not only mean "in concurrent accesses" but more general - accesses from concurrent threads. Thus volatile.

    – Maksim Gumerov
    Mar 27 at 7:46

















So, what does reasonable guru do when they want something like that? -- and your answer is : synchronized. After a while and if there's time, someone will probably change that to some sort of efficient locking mechanism like StampedLock or even manual, sequential, unsynchronized population of a ConcurrentHashMap - which is classical and proven ... although maybe not as "beautiful" compared to stream population. Actual software engineers dont care about beauty all the time - readability, maintainability and stability are much more important

– specializt
Mar 27 at 7:12






So, what does reasonable guru do when they want something like that? -- and your answer is : synchronized. After a while and if there's time, someone will probably change that to some sort of efficient locking mechanism like StampedLock or even manual, sequential, unsynchronized population of a ConcurrentHashMap - which is classical and proven ... although maybe not as "beautiful" compared to stream population. Actual software engineers dont care about beauty all the time - readability, maintainability and stability are much more important

– specializt
Mar 27 at 7:12





3




3





AFAIR (but I can't find any reference), Spring makes sure there is a happens-before, i.e. the injection of the beans happens before their usage. There should be nothing to worry about. And I don't know of any map (and certainly not the HashMap used by Collectors.toMap()), that would by itself decide to change its internal structure when you only read from it. That said, I would indeed favor constructor injection to setter injection.

– JB Nizet
Mar 27 at 7:14





AFAIR (but I can't find any reference), Spring makes sure there is a happens-before, i.e. the injection of the beans happens before their usage. There should be nothing to worry about. And I don't know of any map (and certainly not the HashMap used by Collectors.toMap()), that would by itself decide to change its internal structure when you only read from it. That said, I would indeed favor constructor injection to setter injection.

– JB Nizet
Mar 27 at 7:14













i completely missed the fact that the question is about setter injection and a spring singleton. Well in that case : Yes, it doesnt actually matter because injection happens only once per singleton bean

– specializt
Mar 27 at 7:17





i completely missed the fact that the question is about setter injection and a spring singleton. Well in that case : Yes, it doesnt actually matter because injection happens only once per singleton bean

– specializt
Mar 27 at 7:17













"only once" - it's irrelevant, I don't care how many times it happens, I care about whether the results of that are observed by everyone. Even if something happened eons ago, it might be not yet observed by some thread without proper happens-before. JB Nizet's answer says Spring makes sure of that - I heard that as well and I'll try to find specifics on that.

– Maksim Gumerov
Mar 27 at 7:43





"only once" - it's irrelevant, I don't care how many times it happens, I care about whether the results of that are observed by everyone. Even if something happened eons ago, it might be not yet observed by some thread without proper happens-before. JB Nizet's answer says Spring makes sure of that - I heard that as well and I'll try to find specifics on that.

– Maksim Gumerov
Mar 27 at 7:43













" by itself decide to change its internal structure when you only read from it." - no of course not that, I was trying to explain that while it's being populated it might and will change its structure, and since it's not thread safe, no one can be sure further reading from it will work well. Thread safety does not only mean "in concurrent accesses" but more general - accesses from concurrent threads. Thus volatile.

– Maksim Gumerov
Mar 27 at 7:46






" by itself decide to change its internal structure when you only read from it." - no of course not that, I was trying to explain that while it's being populated it might and will change its structure, and since it's not thread safe, no one can be sure further reading from it will work well. Thread safety does not only mean "in concurrent accesses" but more general - accesses from concurrent threads. Thus volatile.

– Maksim Gumerov
Mar 27 at 7:46













2 Answers
2






active

oldest

votes


















0















Or maybe I am just making up problems no one ever actually encountered?




I think may be conflating your assignment with the problems historically seen from double-checked locking:



private Foo foo; // this is an instance variable

public Foo getFoo()
if (foo != null)
synchronized (this)
if (foo != null)
foo = new Foo();



return foo;



This code appears to be thread-safe: you do an initial, presumed quick, check to verify that the value has not been initialized yet, and if it hasn't you initialize in a synchronized block. The problem is that the new operation is distinct from the constructor call, and some implementations were assigning the reference returned by new to the variable before the constructor ran. The result was that another thread could see that value before the constructor completed.



In your case, however, you are assigning the variable based on the result of a function call. The Map created by the function call is not assigned to the variable until the function returns. The compiler (including Hotspot) is not permitted to re-order this operation because such a change would be visible to the thread that's executing the function, and would not therefore be sequentially consistent per JLS 17.4.3.



That out of the way, here are some additional comments:




Initialize and populate the Map in an autowired constructor, which frankly I prefer




As do the creators of the Guice dependency injection framework. One reason to prefer constructor injection is that you know that you'll never see the bean in an inconsistent state.



The reason that Spring encourages (or at least does not discourage) setter injection is because it makes circular references possible. You can decide for yourself whether circular references are a good idea.




Initialize the Map to an empty final ConcurrentHashMap, then populate it in a setter




This is a bad idea because it's likely that other threads will see a partially constructed map. It's far better to see either null or a fully-constructed map, because you can compensate for the first case.




Use volatile on the field. Slightly degrades performance without any need



Use synchronized to access the field and read its values. Clearly even worse than (c).




Don't let perceived performance impacts keep you from writing correct code. The only time that synchronization will significantly impact your performance is when concurrent threads access a synchronized variable/method within a tight loop. If you're not in a loop, then the memory barrier adds an irrelevant amount of time to your call (and even in a loop it's minimal unless you need to wait for a value to arrive in your core's cache).



In this case it doesn't matter, but I would guess that getProcessors() takes a tiny percentage of your total execution time, and that a far larger amount of time is taken by running the processor(s).






share|improve this answer

























  • "Don't let perceived performance impacts keep you from writing correct code." - sure, I just would like to avoid that it there is a cleaner solution (or if for some reason there is no problem). And thanks for interesting insights regarding new+assignment. But I don't see actual answer: what do you propose me to do? "In your case, however" implies that you don't think there is a problem.

    – Maksim Gumerov
    Mar 29 at 3:47











  • Also, the code you cited at least contains synchronization. The initial code I shown does not. So, it's probably still buggy like I said. So, there is a problem and it needs a solution. What is the one you actually say is an answer?

    – Maksim Gumerov
    Mar 29 at 3:51












  • just use toConcurrentMap and get it over with. It is impossible for the map to be in an inconsistent state after that - you're trying to solve problems which do not exist and your time surely can be invested in a better way ... by reading up on spring CDI and @Required, for instance

    – specializt
    Mar 29 at 7:45












  • @MaksimGumerov - the example code I wrote is a case where multi-thread visibility is a problem. I wrote it to compare to the code that you wrote, in which multi-thread visibility is not a problem, due to the explanation and JLS reference that I gave you.

    – guest
    Mar 29 at 13:48












  • Sure thing, toConcurrentMap solves the map consistency problem. Where did I say it may become inconsistent after that? toConcurrentMap by definition creates a thread-safe map :) You are not adding anything to my initial question with 4 options. But yes, I promised to read up on how Spring guarantees happens-before on injections. Didn't do that yet.

    – Maksim Gumerov
    Apr 1 at 17:16



















0














Thanks to hints of commenters here, after googling a bit I was able to find not a reference to Spring manual but at least a matter-of-fact guarantee, see Should I mark object attributes as volatile if I init them in @PostConstruct in Spring Framework? - the updated part of accepted answer. In essence it says that every lookup of a particular bean in a context, and hence, roughly, every injection of that bean, is preceded by locking on some monitor, and bean initialization also happens while locked on that same monitor, establishing happens-before relationship between bean initialization and bean injection. More specifially, everything done during bean initialization (like, assignment of processors in MyBean initialization) happens-before subsequent injections of that bean - and the bean is only used after it has been injected. So the author says no volatile is necessary, unless we are going to change the field after that.



That would be my accepted answer (in combination with toConcurrentMap) if not for 2 "buts".



1) This does not mean injection of non-initialized beans offers that same happens-before. And injection of non-initialized beans happens more often that some think. In case of circular dependencied, which are better kept rare but look valid sometimes. In case of lazy initialized beans. Some libraries (AFAIK even some of Spring projects) introduce circular dependencies, I saw that myself. And sometimes you introduce circular deps by accident, that is not treated as error by default. Of course, reasonable code does not use non-initialized beans, but since MyBean could be injected to some bean X before it's initialized, there will be no happens-before after it's initalized, annihilating our guarantees.



2) This is not even a documented feature. Still! But recently it has at least been put on a backlog. See https://github.com/spring-projects/spring-framework/issues/8986 - still, until they documented it we cannot assume it's not subject to changes. Bah, even when they do, it still may be changed in some next version, but at least that will be reflected in some changelist or whatnot.



So, taking those 2 notes into consideration, especially the 1st, I am inclined to say that volatile+toConcurrentMap is the way to go. Right?






share|improve this answer



























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55371418%2fspring-singleton-beans-maps-and-multithreading%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0















    Or maybe I am just making up problems no one ever actually encountered?




    I think may be conflating your assignment with the problems historically seen from double-checked locking:



    private Foo foo; // this is an instance variable

    public Foo getFoo()
    if (foo != null)
    synchronized (this)
    if (foo != null)
    foo = new Foo();



    return foo;



    This code appears to be thread-safe: you do an initial, presumed quick, check to verify that the value has not been initialized yet, and if it hasn't you initialize in a synchronized block. The problem is that the new operation is distinct from the constructor call, and some implementations were assigning the reference returned by new to the variable before the constructor ran. The result was that another thread could see that value before the constructor completed.



    In your case, however, you are assigning the variable based on the result of a function call. The Map created by the function call is not assigned to the variable until the function returns. The compiler (including Hotspot) is not permitted to re-order this operation because such a change would be visible to the thread that's executing the function, and would not therefore be sequentially consistent per JLS 17.4.3.



    That out of the way, here are some additional comments:




    Initialize and populate the Map in an autowired constructor, which frankly I prefer




    As do the creators of the Guice dependency injection framework. One reason to prefer constructor injection is that you know that you'll never see the bean in an inconsistent state.



    The reason that Spring encourages (or at least does not discourage) setter injection is because it makes circular references possible. You can decide for yourself whether circular references are a good idea.




    Initialize the Map to an empty final ConcurrentHashMap, then populate it in a setter




    This is a bad idea because it's likely that other threads will see a partially constructed map. It's far better to see either null or a fully-constructed map, because you can compensate for the first case.




    Use volatile on the field. Slightly degrades performance without any need



    Use synchronized to access the field and read its values. Clearly even worse than (c).




    Don't let perceived performance impacts keep you from writing correct code. The only time that synchronization will significantly impact your performance is when concurrent threads access a synchronized variable/method within a tight loop. If you're not in a loop, then the memory barrier adds an irrelevant amount of time to your call (and even in a loop it's minimal unless you need to wait for a value to arrive in your core's cache).



    In this case it doesn't matter, but I would guess that getProcessors() takes a tiny percentage of your total execution time, and that a far larger amount of time is taken by running the processor(s).






    share|improve this answer

























    • "Don't let perceived performance impacts keep you from writing correct code." - sure, I just would like to avoid that it there is a cleaner solution (or if for some reason there is no problem). And thanks for interesting insights regarding new+assignment. But I don't see actual answer: what do you propose me to do? "In your case, however" implies that you don't think there is a problem.

      – Maksim Gumerov
      Mar 29 at 3:47











    • Also, the code you cited at least contains synchronization. The initial code I shown does not. So, it's probably still buggy like I said. So, there is a problem and it needs a solution. What is the one you actually say is an answer?

      – Maksim Gumerov
      Mar 29 at 3:51












    • just use toConcurrentMap and get it over with. It is impossible for the map to be in an inconsistent state after that - you're trying to solve problems which do not exist and your time surely can be invested in a better way ... by reading up on spring CDI and @Required, for instance

      – specializt
      Mar 29 at 7:45












    • @MaksimGumerov - the example code I wrote is a case where multi-thread visibility is a problem. I wrote it to compare to the code that you wrote, in which multi-thread visibility is not a problem, due to the explanation and JLS reference that I gave you.

      – guest
      Mar 29 at 13:48












    • Sure thing, toConcurrentMap solves the map consistency problem. Where did I say it may become inconsistent after that? toConcurrentMap by definition creates a thread-safe map :) You are not adding anything to my initial question with 4 options. But yes, I promised to read up on how Spring guarantees happens-before on injections. Didn't do that yet.

      – Maksim Gumerov
      Apr 1 at 17:16
















    0















    Or maybe I am just making up problems no one ever actually encountered?




    I think may be conflating your assignment with the problems historically seen from double-checked locking:



    private Foo foo; // this is an instance variable

    public Foo getFoo()
    if (foo != null)
    synchronized (this)
    if (foo != null)
    foo = new Foo();



    return foo;



    This code appears to be thread-safe: you do an initial, presumed quick, check to verify that the value has not been initialized yet, and if it hasn't you initialize in a synchronized block. The problem is that the new operation is distinct from the constructor call, and some implementations were assigning the reference returned by new to the variable before the constructor ran. The result was that another thread could see that value before the constructor completed.



    In your case, however, you are assigning the variable based on the result of a function call. The Map created by the function call is not assigned to the variable until the function returns. The compiler (including Hotspot) is not permitted to re-order this operation because such a change would be visible to the thread that's executing the function, and would not therefore be sequentially consistent per JLS 17.4.3.



    That out of the way, here are some additional comments:




    Initialize and populate the Map in an autowired constructor, which frankly I prefer




    As do the creators of the Guice dependency injection framework. One reason to prefer constructor injection is that you know that you'll never see the bean in an inconsistent state.



    The reason that Spring encourages (or at least does not discourage) setter injection is because it makes circular references possible. You can decide for yourself whether circular references are a good idea.




    Initialize the Map to an empty final ConcurrentHashMap, then populate it in a setter




    This is a bad idea because it's likely that other threads will see a partially constructed map. It's far better to see either null or a fully-constructed map, because you can compensate for the first case.




    Use volatile on the field. Slightly degrades performance without any need



    Use synchronized to access the field and read its values. Clearly even worse than (c).




    Don't let perceived performance impacts keep you from writing correct code. The only time that synchronization will significantly impact your performance is when concurrent threads access a synchronized variable/method within a tight loop. If you're not in a loop, then the memory barrier adds an irrelevant amount of time to your call (and even in a loop it's minimal unless you need to wait for a value to arrive in your core's cache).



    In this case it doesn't matter, but I would guess that getProcessors() takes a tiny percentage of your total execution time, and that a far larger amount of time is taken by running the processor(s).






    share|improve this answer

























    • "Don't let perceived performance impacts keep you from writing correct code." - sure, I just would like to avoid that it there is a cleaner solution (or if for some reason there is no problem). And thanks for interesting insights regarding new+assignment. But I don't see actual answer: what do you propose me to do? "In your case, however" implies that you don't think there is a problem.

      – Maksim Gumerov
      Mar 29 at 3:47











    • Also, the code you cited at least contains synchronization. The initial code I shown does not. So, it's probably still buggy like I said. So, there is a problem and it needs a solution. What is the one you actually say is an answer?

      – Maksim Gumerov
      Mar 29 at 3:51












    • just use toConcurrentMap and get it over with. It is impossible for the map to be in an inconsistent state after that - you're trying to solve problems which do not exist and your time surely can be invested in a better way ... by reading up on spring CDI and @Required, for instance

      – specializt
      Mar 29 at 7:45












    • @MaksimGumerov - the example code I wrote is a case where multi-thread visibility is a problem. I wrote it to compare to the code that you wrote, in which multi-thread visibility is not a problem, due to the explanation and JLS reference that I gave you.

      – guest
      Mar 29 at 13:48












    • Sure thing, toConcurrentMap solves the map consistency problem. Where did I say it may become inconsistent after that? toConcurrentMap by definition creates a thread-safe map :) You are not adding anything to my initial question with 4 options. But yes, I promised to read up on how Spring guarantees happens-before on injections. Didn't do that yet.

      – Maksim Gumerov
      Apr 1 at 17:16














    0












    0








    0








    Or maybe I am just making up problems no one ever actually encountered?




    I think may be conflating your assignment with the problems historically seen from double-checked locking:



    private Foo foo; // this is an instance variable

    public Foo getFoo()
    if (foo != null)
    synchronized (this)
    if (foo != null)
    foo = new Foo();



    return foo;



    This code appears to be thread-safe: you do an initial, presumed quick, check to verify that the value has not been initialized yet, and if it hasn't you initialize in a synchronized block. The problem is that the new operation is distinct from the constructor call, and some implementations were assigning the reference returned by new to the variable before the constructor ran. The result was that another thread could see that value before the constructor completed.



    In your case, however, you are assigning the variable based on the result of a function call. The Map created by the function call is not assigned to the variable until the function returns. The compiler (including Hotspot) is not permitted to re-order this operation because such a change would be visible to the thread that's executing the function, and would not therefore be sequentially consistent per JLS 17.4.3.



    That out of the way, here are some additional comments:




    Initialize and populate the Map in an autowired constructor, which frankly I prefer




    As do the creators of the Guice dependency injection framework. One reason to prefer constructor injection is that you know that you'll never see the bean in an inconsistent state.



    The reason that Spring encourages (or at least does not discourage) setter injection is because it makes circular references possible. You can decide for yourself whether circular references are a good idea.




    Initialize the Map to an empty final ConcurrentHashMap, then populate it in a setter




    This is a bad idea because it's likely that other threads will see a partially constructed map. It's far better to see either null or a fully-constructed map, because you can compensate for the first case.




    Use volatile on the field. Slightly degrades performance without any need



    Use synchronized to access the field and read its values. Clearly even worse than (c).




    Don't let perceived performance impacts keep you from writing correct code. The only time that synchronization will significantly impact your performance is when concurrent threads access a synchronized variable/method within a tight loop. If you're not in a loop, then the memory barrier adds an irrelevant amount of time to your call (and even in a loop it's minimal unless you need to wait for a value to arrive in your core's cache).



    In this case it doesn't matter, but I would guess that getProcessors() takes a tiny percentage of your total execution time, and that a far larger amount of time is taken by running the processor(s).






    share|improve this answer














    Or maybe I am just making up problems no one ever actually encountered?




    I think may be conflating your assignment with the problems historically seen from double-checked locking:



    private Foo foo; // this is an instance variable

    public Foo getFoo()
    if (foo != null)
    synchronized (this)
    if (foo != null)
    foo = new Foo();



    return foo;



    This code appears to be thread-safe: you do an initial, presumed quick, check to verify that the value has not been initialized yet, and if it hasn't you initialize in a synchronized block. The problem is that the new operation is distinct from the constructor call, and some implementations were assigning the reference returned by new to the variable before the constructor ran. The result was that another thread could see that value before the constructor completed.



    In your case, however, you are assigning the variable based on the result of a function call. The Map created by the function call is not assigned to the variable until the function returns. The compiler (including Hotspot) is not permitted to re-order this operation because such a change would be visible to the thread that's executing the function, and would not therefore be sequentially consistent per JLS 17.4.3.



    That out of the way, here are some additional comments:




    Initialize and populate the Map in an autowired constructor, which frankly I prefer




    As do the creators of the Guice dependency injection framework. One reason to prefer constructor injection is that you know that you'll never see the bean in an inconsistent state.



    The reason that Spring encourages (or at least does not discourage) setter injection is because it makes circular references possible. You can decide for yourself whether circular references are a good idea.




    Initialize the Map to an empty final ConcurrentHashMap, then populate it in a setter




    This is a bad idea because it's likely that other threads will see a partially constructed map. It's far better to see either null or a fully-constructed map, because you can compensate for the first case.




    Use volatile on the field. Slightly degrades performance without any need



    Use synchronized to access the field and read its values. Clearly even worse than (c).




    Don't let perceived performance impacts keep you from writing correct code. The only time that synchronization will significantly impact your performance is when concurrent threads access a synchronized variable/method within a tight loop. If you're not in a loop, then the memory barrier adds an irrelevant amount of time to your call (and even in a loop it's minimal unless you need to wait for a value to arrive in your core's cache).



    In this case it doesn't matter, but I would guess that getProcessors() takes a tiny percentage of your total execution time, and that a far larger amount of time is taken by running the processor(s).







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Mar 28 at 14:55









    guestguest

    3513 bronze badges




    3513 bronze badges















    • "Don't let perceived performance impacts keep you from writing correct code." - sure, I just would like to avoid that it there is a cleaner solution (or if for some reason there is no problem). And thanks for interesting insights regarding new+assignment. But I don't see actual answer: what do you propose me to do? "In your case, however" implies that you don't think there is a problem.

      – Maksim Gumerov
      Mar 29 at 3:47











    • Also, the code you cited at least contains synchronization. The initial code I shown does not. So, it's probably still buggy like I said. So, there is a problem and it needs a solution. What is the one you actually say is an answer?

      – Maksim Gumerov
      Mar 29 at 3:51












    • just use toConcurrentMap and get it over with. It is impossible for the map to be in an inconsistent state after that - you're trying to solve problems which do not exist and your time surely can be invested in a better way ... by reading up on spring CDI and @Required, for instance

      – specializt
      Mar 29 at 7:45












    • @MaksimGumerov - the example code I wrote is a case where multi-thread visibility is a problem. I wrote it to compare to the code that you wrote, in which multi-thread visibility is not a problem, due to the explanation and JLS reference that I gave you.

      – guest
      Mar 29 at 13:48












    • Sure thing, toConcurrentMap solves the map consistency problem. Where did I say it may become inconsistent after that? toConcurrentMap by definition creates a thread-safe map :) You are not adding anything to my initial question with 4 options. But yes, I promised to read up on how Spring guarantees happens-before on injections. Didn't do that yet.

      – Maksim Gumerov
      Apr 1 at 17:16


















    • "Don't let perceived performance impacts keep you from writing correct code." - sure, I just would like to avoid that it there is a cleaner solution (or if for some reason there is no problem). And thanks for interesting insights regarding new+assignment. But I don't see actual answer: what do you propose me to do? "In your case, however" implies that you don't think there is a problem.

      – Maksim Gumerov
      Mar 29 at 3:47











    • Also, the code you cited at least contains synchronization. The initial code I shown does not. So, it's probably still buggy like I said. So, there is a problem and it needs a solution. What is the one you actually say is an answer?

      – Maksim Gumerov
      Mar 29 at 3:51












    • just use toConcurrentMap and get it over with. It is impossible for the map to be in an inconsistent state after that - you're trying to solve problems which do not exist and your time surely can be invested in a better way ... by reading up on spring CDI and @Required, for instance

      – specializt
      Mar 29 at 7:45












    • @MaksimGumerov - the example code I wrote is a case where multi-thread visibility is a problem. I wrote it to compare to the code that you wrote, in which multi-thread visibility is not a problem, due to the explanation and JLS reference that I gave you.

      – guest
      Mar 29 at 13:48












    • Sure thing, toConcurrentMap solves the map consistency problem. Where did I say it may become inconsistent after that? toConcurrentMap by definition creates a thread-safe map :) You are not adding anything to my initial question with 4 options. But yes, I promised to read up on how Spring guarantees happens-before on injections. Didn't do that yet.

      – Maksim Gumerov
      Apr 1 at 17:16

















    "Don't let perceived performance impacts keep you from writing correct code." - sure, I just would like to avoid that it there is a cleaner solution (or if for some reason there is no problem). And thanks for interesting insights regarding new+assignment. But I don't see actual answer: what do you propose me to do? "In your case, however" implies that you don't think there is a problem.

    – Maksim Gumerov
    Mar 29 at 3:47





    "Don't let perceived performance impacts keep you from writing correct code." - sure, I just would like to avoid that it there is a cleaner solution (or if for some reason there is no problem). And thanks for interesting insights regarding new+assignment. But I don't see actual answer: what do you propose me to do? "In your case, however" implies that you don't think there is a problem.

    – Maksim Gumerov
    Mar 29 at 3:47













    Also, the code you cited at least contains synchronization. The initial code I shown does not. So, it's probably still buggy like I said. So, there is a problem and it needs a solution. What is the one you actually say is an answer?

    – Maksim Gumerov
    Mar 29 at 3:51






    Also, the code you cited at least contains synchronization. The initial code I shown does not. So, it's probably still buggy like I said. So, there is a problem and it needs a solution. What is the one you actually say is an answer?

    – Maksim Gumerov
    Mar 29 at 3:51














    just use toConcurrentMap and get it over with. It is impossible for the map to be in an inconsistent state after that - you're trying to solve problems which do not exist and your time surely can be invested in a better way ... by reading up on spring CDI and @Required, for instance

    – specializt
    Mar 29 at 7:45






    just use toConcurrentMap and get it over with. It is impossible for the map to be in an inconsistent state after that - you're trying to solve problems which do not exist and your time surely can be invested in a better way ... by reading up on spring CDI and @Required, for instance

    – specializt
    Mar 29 at 7:45














    @MaksimGumerov - the example code I wrote is a case where multi-thread visibility is a problem. I wrote it to compare to the code that you wrote, in which multi-thread visibility is not a problem, due to the explanation and JLS reference that I gave you.

    – guest
    Mar 29 at 13:48






    @MaksimGumerov - the example code I wrote is a case where multi-thread visibility is a problem. I wrote it to compare to the code that you wrote, in which multi-thread visibility is not a problem, due to the explanation and JLS reference that I gave you.

    – guest
    Mar 29 at 13:48














    Sure thing, toConcurrentMap solves the map consistency problem. Where did I say it may become inconsistent after that? toConcurrentMap by definition creates a thread-safe map :) You are not adding anything to my initial question with 4 options. But yes, I promised to read up on how Spring guarantees happens-before on injections. Didn't do that yet.

    – Maksim Gumerov
    Apr 1 at 17:16






    Sure thing, toConcurrentMap solves the map consistency problem. Where did I say it may become inconsistent after that? toConcurrentMap by definition creates a thread-safe map :) You are not adding anything to my initial question with 4 options. But yes, I promised to read up on how Spring guarantees happens-before on injections. Didn't do that yet.

    – Maksim Gumerov
    Apr 1 at 17:16














    0














    Thanks to hints of commenters here, after googling a bit I was able to find not a reference to Spring manual but at least a matter-of-fact guarantee, see Should I mark object attributes as volatile if I init them in @PostConstruct in Spring Framework? - the updated part of accepted answer. In essence it says that every lookup of a particular bean in a context, and hence, roughly, every injection of that bean, is preceded by locking on some monitor, and bean initialization also happens while locked on that same monitor, establishing happens-before relationship between bean initialization and bean injection. More specifially, everything done during bean initialization (like, assignment of processors in MyBean initialization) happens-before subsequent injections of that bean - and the bean is only used after it has been injected. So the author says no volatile is necessary, unless we are going to change the field after that.



    That would be my accepted answer (in combination with toConcurrentMap) if not for 2 "buts".



    1) This does not mean injection of non-initialized beans offers that same happens-before. And injection of non-initialized beans happens more often that some think. In case of circular dependencied, which are better kept rare but look valid sometimes. In case of lazy initialized beans. Some libraries (AFAIK even some of Spring projects) introduce circular dependencies, I saw that myself. And sometimes you introduce circular deps by accident, that is not treated as error by default. Of course, reasonable code does not use non-initialized beans, but since MyBean could be injected to some bean X before it's initialized, there will be no happens-before after it's initalized, annihilating our guarantees.



    2) This is not even a documented feature. Still! But recently it has at least been put on a backlog. See https://github.com/spring-projects/spring-framework/issues/8986 - still, until they documented it we cannot assume it's not subject to changes. Bah, even when they do, it still may be changed in some next version, but at least that will be reflected in some changelist or whatnot.



    So, taking those 2 notes into consideration, especially the 1st, I am inclined to say that volatile+toConcurrentMap is the way to go. Right?






    share|improve this answer





























      0














      Thanks to hints of commenters here, after googling a bit I was able to find not a reference to Spring manual but at least a matter-of-fact guarantee, see Should I mark object attributes as volatile if I init them in @PostConstruct in Spring Framework? - the updated part of accepted answer. In essence it says that every lookup of a particular bean in a context, and hence, roughly, every injection of that bean, is preceded by locking on some monitor, and bean initialization also happens while locked on that same monitor, establishing happens-before relationship between bean initialization and bean injection. More specifially, everything done during bean initialization (like, assignment of processors in MyBean initialization) happens-before subsequent injections of that bean - and the bean is only used after it has been injected. So the author says no volatile is necessary, unless we are going to change the field after that.



      That would be my accepted answer (in combination with toConcurrentMap) if not for 2 "buts".



      1) This does not mean injection of non-initialized beans offers that same happens-before. And injection of non-initialized beans happens more often that some think. In case of circular dependencied, which are better kept rare but look valid sometimes. In case of lazy initialized beans. Some libraries (AFAIK even some of Spring projects) introduce circular dependencies, I saw that myself. And sometimes you introduce circular deps by accident, that is not treated as error by default. Of course, reasonable code does not use non-initialized beans, but since MyBean could be injected to some bean X before it's initialized, there will be no happens-before after it's initalized, annihilating our guarantees.



      2) This is not even a documented feature. Still! But recently it has at least been put on a backlog. See https://github.com/spring-projects/spring-framework/issues/8986 - still, until they documented it we cannot assume it's not subject to changes. Bah, even when they do, it still may be changed in some next version, but at least that will be reflected in some changelist or whatnot.



      So, taking those 2 notes into consideration, especially the 1st, I am inclined to say that volatile+toConcurrentMap is the way to go. Right?






      share|improve this answer



























        0












        0








        0







        Thanks to hints of commenters here, after googling a bit I was able to find not a reference to Spring manual but at least a matter-of-fact guarantee, see Should I mark object attributes as volatile if I init them in @PostConstruct in Spring Framework? - the updated part of accepted answer. In essence it says that every lookup of a particular bean in a context, and hence, roughly, every injection of that bean, is preceded by locking on some monitor, and bean initialization also happens while locked on that same monitor, establishing happens-before relationship between bean initialization and bean injection. More specifially, everything done during bean initialization (like, assignment of processors in MyBean initialization) happens-before subsequent injections of that bean - and the bean is only used after it has been injected. So the author says no volatile is necessary, unless we are going to change the field after that.



        That would be my accepted answer (in combination with toConcurrentMap) if not for 2 "buts".



        1) This does not mean injection of non-initialized beans offers that same happens-before. And injection of non-initialized beans happens more often that some think. In case of circular dependencied, which are better kept rare but look valid sometimes. In case of lazy initialized beans. Some libraries (AFAIK even some of Spring projects) introduce circular dependencies, I saw that myself. And sometimes you introduce circular deps by accident, that is not treated as error by default. Of course, reasonable code does not use non-initialized beans, but since MyBean could be injected to some bean X before it's initialized, there will be no happens-before after it's initalized, annihilating our guarantees.



        2) This is not even a documented feature. Still! But recently it has at least been put on a backlog. See https://github.com/spring-projects/spring-framework/issues/8986 - still, until they documented it we cannot assume it's not subject to changes. Bah, even when they do, it still may be changed in some next version, but at least that will be reflected in some changelist or whatnot.



        So, taking those 2 notes into consideration, especially the 1st, I am inclined to say that volatile+toConcurrentMap is the way to go. Right?






        share|improve this answer













        Thanks to hints of commenters here, after googling a bit I was able to find not a reference to Spring manual but at least a matter-of-fact guarantee, see Should I mark object attributes as volatile if I init them in @PostConstruct in Spring Framework? - the updated part of accepted answer. In essence it says that every lookup of a particular bean in a context, and hence, roughly, every injection of that bean, is preceded by locking on some monitor, and bean initialization also happens while locked on that same monitor, establishing happens-before relationship between bean initialization and bean injection. More specifially, everything done during bean initialization (like, assignment of processors in MyBean initialization) happens-before subsequent injections of that bean - and the bean is only used after it has been injected. So the author says no volatile is necessary, unless we are going to change the field after that.



        That would be my accepted answer (in combination with toConcurrentMap) if not for 2 "buts".



        1) This does not mean injection of non-initialized beans offers that same happens-before. And injection of non-initialized beans happens more often that some think. In case of circular dependencied, which are better kept rare but look valid sometimes. In case of lazy initialized beans. Some libraries (AFAIK even some of Spring projects) introduce circular dependencies, I saw that myself. And sometimes you introduce circular deps by accident, that is not treated as error by default. Of course, reasonable code does not use non-initialized beans, but since MyBean could be injected to some bean X before it's initialized, there will be no happens-before after it's initalized, annihilating our guarantees.



        2) This is not even a documented feature. Still! But recently it has at least been put on a backlog. See https://github.com/spring-projects/spring-framework/issues/8986 - still, until they documented it we cannot assume it's not subject to changes. Bah, even when they do, it still may be changed in some next version, but at least that will be reflected in some changelist or whatnot.



        So, taking those 2 notes into consideration, especially the 1st, I am inclined to say that volatile+toConcurrentMap is the way to go. Right?







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Apr 1 at 17:52









        Maksim GumerovMaksim Gumerov

        3722 silver badges19 bronze badges




        3722 silver badges19 bronze badges






























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55371418%2fspring-singleton-beans-maps-and-multithreading%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

            용인 삼성생명 블루밍스 목차 통계 역대 감독 선수단 응원단 경기장 같이 보기 외부 링크 둘러보기 메뉴samsungblueminx.comeh선수 명단용인 삼성생명 블루밍스용인 삼성생명 블루밍스ehsamsungblueminx.comeheheheh

            155 수학 과학 기타 둘러보기 메뉴eh추가해eh문서를 완성해