Spring is in the bean thread-safe?

Conclusion: not thread-safe

Spring container Bean whether thread safety, the container itself does not provide Bean thread security policy, it can be said Bean Spring container itself does not have thread-safe features, but is specific to combine specific scope of Bean to study.

Spring bean scopes (scope) type
  1, singleton: single embodiment, default scope.

  2, prototype: prototype, each time a new object is created.

  3, request: request, every Http request to create a new object for the next WebApplicationContext environment.

  4, session: a session, a session share the same instance, use different sessions unused instances.

  5, global-session: a global session, a session sharing all instances.

Thread-safety issue, from single cases are explained with the prototype Bean.

Bean prototype
  for prototype Bean, every time you create a new object, that is, there is no Bean shared between threads, naturally there will be no thread safety issues.

Singleton Bean
  for singleton Bean, all threads share a singleton instance Bean, and therefore there is a resource competition.

  If singleton Bean, is a stateless Bean , that is, the operation will not be executed on the thread of the members of Bean's query operations other than, then the singleton Bean thread safe. For example, the Spring mvc Controller, Service, Dao, etc. These are mostly stateless Bean, only focus on the process itself.

 

 

spring Singleton, why controller, service and dao can really guarantee thread safety?

  The default Spring Bean single embodiment mode, the frame and not the bean encapsulation process multiple threads.
  In fact most of the time Bean is stateless (such as Dao) So in a way, Bean is actually safe.
  But if there is a state of Bean developer would need to carry out their own thread-safe guarantee, the easiest way is to change the scope of the bean to "singleton" changed '' protopyte 'so that each request is equivalent to new Bean Bean () so that you can ensure the safety of the thread.

  There is a state data storage function
  stateless data is not saved
  

  controller, itself is not thread-safe service and dao layer, but only if the method call inside, and multi-thread calls an instance method copies the variables in memory, which is the working memory of its own thread, is safe.

  Want to understand the principles can take a look at "in-depth understanding of JVM virtual machine", section 2.2.2:

Java virtual machine thread stack is private, its life cycle and the same thread. Is a virtual machine stack Java memory model described method performed: each method is created while executing a stack frame used to store information local variable table, the operand stack, dynamic linking, method exports.

 

  "Java Concurrency in combat" Section 3.2.2:

One of the inherent properties of the local variable is enclosed in a thread of execution. 
They are located in executing thread stack, other threads can not access the stack.

  So in fact, any stateless singleton are thread safe.
  Spring is simply built up a system by which a large number of single cases, the script is provided by way of transaction services

 

You can also look at this deeper understanding:  thread-safety issues on the Spring @Controller @Service etc.

First ask @Controller @Service is not thread safe?
  A: The default configuration it is not. why? Because the default @Controller without adding @Scope, the default value is not added @Scope singleton, singleton. It means that the system is initialized only once Controller container, so every time the request is the same Controller container, of course not thread-safe. For chestnut:

@RestController
 public  class TestController { 

    Private  int var = 0 ; 
    
    @GetMapping (value = "/ test_var" )
     public String Test () { 
        System.out.println ( "Common Variables var:" + (++ var));
         return " common variable var: "+ var; 
    } 
}

Postman made three requests in which the following results:

Common variable var: 1 
common variable var: 2 
common variable var: 3

That he is not thread safe. How to do it? He can add to the above said @Scope notes, as follows:  

@RestController 
@Scope (value = "the prototype") // add @Scope annotations, he has two values: singleton instance -singleton multiple -prototype 
public  class TestController { 

    Private  int var = 0 ; 
    
    @GetMapping (value = " / test_var " )
     public String Test () { 
        System.out.println ( " Common variables var: "+ (++ var));
         return " Common variables var: "+ var; 
    } 
}

As a result, each request to create a single Controller container, so between each request is thread-safe, three requests results:

Common variable var: 1 
Common variable var: 1 
Common variable var: 1

Plus a number of examples of prototype @Scope annotation is not necessarily thread-safe?  

@RestController 
@Scope (value = "the prototype") // add @Scope annotations, he has two values: singleton instance -singleton multiple -prototype 
public  class TestController {
     Private  int var = 0 ;
     Private  static  int the staticVar = 0 ; 

    @GetMapping (value = "/ test_var" )
     public String Test () { 
        System.out.println ( "Common variables var:" + (++ var) + "--- static variable the staticVar:" + (++ the staticVar ));
         return "Common variables var:" + var + "static variable the staticVar:" + the staticVar; 
    } 
}

The Three requests results:

Common variable var: 1 --- static variable staticVar: 1 
Common variable var: 1 --- static variable staticVar: 2 
common variable var: 1 --- static variable staticVar: 3

  Although every time create a separate Controller but he could not carry variable itself is static Yeah, so I say, even add annotations @Scope not necessarily guarantee 100% of the Controller thread safe. So whether thread safety is how to define the variables, and Controller configuration. Therefore, almost to the point of full test, as follows:  

@RestController 
@Scope (value = "Singleton") // the prototype Singleton 
public  class TestController { 

    Private  int var = 0; // define a common variable 

    Private  static  int the staticVar = 0; // define a static variable 

    @Value ( "{$ } int-Test " )
     Private  int testInt; // read from the configuration file variable 

    ThreadLocal <Integer> = TL new new ThreadLocal <> (); // with encapsulated ThreadLocal variable 

    @Autowired 
    Private the User User; // injecting a subject to encapsulate variable

    @GetMapping (value = "/ test_var" )
     public String Test () { 
        tl.set ( . 1 ); 
        System.out.println ( "first to take values about the user object:" + user.getAge () + " === then take a look at hashCode: "+ user.hashCode ()); 
        user.setAge ( 1 ); 
        System.out.println ( " ordinary variables var: "+ (++ var) +" === static variable staticVar: "+ (++ staticVar) + "=== configuration variables testInt:" + (++ testInt)
                 + "=== the ThreadLocal variables tl:" + tl.get () + "=== injection variable User:" + User. getAge ());
         return "Common variables var:" + var + ", static variable staticVar:" + staticVar + ", configuration read variable testInt:" + testInt + ",ThreadLocal variable TL: " 
                + tl.get () +" implantation variable user: "+ user.getAge();
    }
}

Code outside complement the Controller:
config inside their own definition of Bean: User

@Configuration
public class MyConfig {
    @Bean
    public User user(){
        return new User();
    }
}

Define a variable way I can think of being on so many, three times http request as follows:

Take the user to look at the value of the object: 0 === then take about hashCode: 241165852 
common variable var: 1 === static variable staticVar: 1 === Configuration variable testInt: 1 === ThreadLocal variable tl: 1 === injection user variables: 1 
to take values about the user object: 1 === then take about hashCode: 241165852 
common variable var: 2 === static variable staticVar: 2 === configuration variable testInt: 2 === ThreadLocal variables tl : 1 === user variable injection: 1 
to take values about the user object: 1 === then take about hashCode: 241165852 
common variable var: 3 === static variables staticVar: 3 === configuration variable testInt: 3 = == ThreadLocal variable tl: 1 === injection variable user: 1

  It can be seen in a single embodiment mode Controller Only ThreadLocal variable is thread safe package. Why do you say this way? We can see the results of which only three requests ThreadLocal variable values from each time, several other are cumulative, and user objects of it, the default value is 00 + 1 = 1, the value of the second cross time is already 1, the key to his hashCode is the same, indicating that each call is the same user object request.
The annotation on @Scope TestController The change into the following properties of the multi-instance: @Scope (value = "prototype" ), others are the same, the request again with the following results:

Take the user to look at the value of the object: 0 === then take about hashCode: 853315860 
common variable var: 1 === static variable staticVar: 1 === Configuration variable testInt: 1 === ThreadLocal variable tl: 1 === injection user variables: 1 
to take values about the user object: 1 === then take about hashCode: 853315860 
common variable var: 1 === static variable staticVar: 2 === configuration variable testInt: 1 === ThreadLocal variables tl : 1 === user variable injection: 1 
to take values about the user object: 1 === then take about hashCode: 853315860 
common variable var: 1 === static variable staticVar: 3 === configuration variable testInt: 1 = == ThreadLocal variable tl: 1 === injection variable user: 1

  This analysis found that under variable multi-instance mode ordinary variables, as well as take the configuration of ThreadLocal variables are thread-safe, and static variables and user (see his hashCode are the same) object variables are not thread-safe . That time although TestController is initialized every request an object, but is always only one static variable, and this object is also injected into the user's only one. Only a static variable which is of course slightly, then there is no way to get every new user object can be a new one? of course can:

public class MyConfig {
    @Bean
    @Scope(value = "prototype")
    public User user(){
        return new User();
    }    
}

In the config inside to the injection of the same Bean plus a comment @Scope(value = "prototype")on it, again requesting it and see:

Take the user to look at the value of the object: 0 === then take about hashCode: 1612967699 
common variable var: 1 === static variable staticVar: 1 === Configuration variable testInt: 1 === ThreadLocal variable tl: 1 === injection user variables:. 1 
to take values about the user object: 0 === then take about hashCode: 985418837 
common variable var: 1 === static variable staticVar: 2 === configuration variable testInt: 1 === ThreadLocal variables tl : 1 === user variable injection: a 
first user to take values about the object: 0 === then take about hashCode: 1958952789 
common variable var: 1 === static variable staticVar: 3 === configuration variable testInt: 1 = == ThreadLocal variable tl: 1 === injection variable user: 1

HashCode user can not see the object of each request is the same, each taking the value of the variable before the user is assigned are also the default value of 0.
The following summary:

  1 in @ Controller / @ Service container such as, by default, scope -singleton embodiment is a single value, and it is thread safe.
  2, try not to define a static variable @ Controller / @ Service and other containers, whether singleton (singleton) or multi-instance (prototype) he is thread safe.
  3, the default Bean object injected, not when he also set the scope thread safe.
  4, be sure to define the variable, then use ThreadLocal to encapsulate, this is a thread-safe

 

Guess you like

Origin www.cnblogs.com/myseries/p/11729800.html