Hello everyone, I am not Chen Mou~
Spring’s beans are all singletons by default, in some cases, singletons are concurrent unsafe, taking the Controller as an example, the root cause of the problem is that we may define member variables in the Controller, so that multiple requests come in, enter the Controller object of the same singleton, and modify the value of this member variable, so they will affect each other and cannot achieve concurrency safety (different from the concept of thread isolation, The effect of this will be explained later.
First, let’s take an example to prove that the concurrency of a single instance is not safe:
Visiting this url multiple times, you can see that each time the result is self-incrementing, so such code is obviously unsafe for concurrency.
Therefore, in order to make the stateless mass of Http requests unaffected, we can take the following measures:
For web projects, you can annotate @Scope (“prototype”) or @Scope (“request”) on the Controller class, and for non-web projects, add annotations to the Component class @Scope (“prototype”).
Advantages: simple implementation;
Disadvantages: Greatly increases the server resource overhead of bean creation instantiation destruction.
Someone thought of the thread isolation class ThreadLocal, we tried to wrap the member variable as ThreadLocal in an attempt to achieve concurrency safety, while printing out the thread name of the Http request, modifying the code as follows:
Access this url multiple times to test a hand, print the log as follows:
From the log analysis, more than twenty consecutive requests get results of 1 and 2 and 3, and we expect that no matter how many concurrent requests I have, the result of each time is 1; At the same time, it can be found that the default request thread pool size of the web server is 10, and these 10 core threads can be reused by different Http requests later, so this is why the results of the same thread name are not duplicated.
Summary: ThreadLocal can achieve thread isolation, but it still cannot achieve concurrency safety.
Some people say that the member variables of the singleton bean are so troublesome, you can try to avoid using the member variables as much as possible, and replace the member variables with local variables in the RequestMapping method under the conditions allowed by the business, which is more convenient. This method is naturally the most appropriate, and I am also the most recommended. The code has been modified to read as follows:
But what do we do when there are very few cases where member variables have to be used?
Java as a super functional programming language, rich API, if you have to use member variables in a singleton bean, you can consider using concurrency-safe containers, such as ConcurrentHashMap, ConcurrentHashSet, etc., and wrap our member variables (generally can be currently running task lists and other such variables) into these concurrency-safe containers for management.
If you also have to further consider the impact of microservices or distributed services, Mode 4 is not enough to deal with, so you can use distributed cache middleware that can share some information, such as Redis, etc., so that different service instances of the same service have the same share of information (such as variables such as the currently running task list).
Spring bean scopes have the following 5:
(The following is only used under the web project)
The beautiful boys are liking, sharing, and watching the three consecutive times