0

Are methods (without using class variables) thread safe when using Spring Boot ? I came across carious links where they mentioned instance variables aren't safe always ?

My doubt is how can I create a race condition ? Is the below code thread safe ?And if yes then how can i make it thread - unsafe without using class variables

 @RestController
        public class GreetingController {
        
            @Autowired
            private GreetingService greetingService;
        
            @GetMapping("/hello")
            public void greeting(@RequestBody MyUser myUser) throws Exception  {
                greetingService.getData(myUser);
             }  

 @Service
    public class GreetingService {
        
        @Autowired
        private DBService dBService;
        
        public void getData (MyUser m ) throws InterruptedException
        {
            
            dBService.getData(m);
        }




@Repository
         public class DBService {
    
        
           public MyUser getData(MyUser myUser) throws InterruptedException {
            
            System.out.println( "message  before: "  + myUser.getA() + " Thread : " +Thread.currentThread().getName());
    
            
            Thread.sleep(18000);
            System.out.println( "message after "  + myUser.getA() + " Thread : " +Thread.currentThread().getName());
            
            return myUser;
            
            
        }
Pale Blue Dot
  • 511
  • 2
  • 13
  • 33

2 Answers2

1

In resume: yes, apparently, this code is thread-safe. Since you're using Servlets, each request will be served in a different thread provided by the servlet container (if you're using the default configurations for Spring Boot, the servlet container is a Embedded Tomcat).

Why apparently? Because this code is only thread-safe if the instances of objects declared in the class scope are also thread-safe (i.e GreetingService must be thread-safe)

Take your own example:

The Thread#sleep executed in a first request has no effect on the subsequent ones (i.e other request will not be blocked) because the subsequent ones are served on different threads, as said above.

You will be fine as long as you don't assign new values to the global variables during a request life cycle.

Matheus
  • 3,058
  • 7
  • 16
  • 37
  • @Matheus.Thanks for the explanation. So unless I am using class variables and changing its state .i am fine.That's what i understood. – Pale Blue Dot Jun 19 '21 at 15:25
  • Correct. Do not manage state on Singleton beans that are shared between multiple threads, especially in a web environment. That may cause problems and then becomes thread-unsafe – Matheus Jun 19 '21 at 15:26
  • Just last doubt .If I wanted to share states between different threads what's the recommended way?esp in Spring – Pale Blue Dot Jun 19 '21 at 15:32
  • 1
    I think ensuring that only one thread at a time is allowed to change the object (by using the `synchronized` keyword) is a fine way to go. I've never had to share state between threads, so maybe i'm not the best person to answer this. – Matheus Jun 19 '21 at 20:43
0

By default (see Does spring dependency injection create singleton objects?), objects injected by spring dependency injection (@Autowired in your case) are singletons.

In your example, there will be exactly one instance each of the controller, service, and repository. So, not inherently thread-safe.

The usual pattern for these classes is as you have shown - use class-level variables only for instances of objects that are themselves thread-safe.

Do not keep any state in class-level variables unless you want that data shared (which is rare), and your code will be thread-safe.

If you do share state on purpose, make sure that you take care to make access to that state thread-safe.

GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67
  • Thanks.But is my code above thread safe ?If not how? – Pale Blue Dot Jun 19 '21 at 15:21
  • 1
    All of it looks threadsafe to me except for maybe your DBService, which I'm guessing is not your real code anyway. If that were a "normal" database service that used a JDBC connection pool to access a database and return a result (without mutating any instance variables), then that would definitely be threadsafe too. – GreyBeardedGeek Jun 20 '21 at 00:20