0

I'm new to Spring and have some basic question.In one of the Spring examples as given below, I noticed EmployeeManager is Autowired.

Question:

  1. The EmployeeManager scope is not given, so I would assume the default scope is SINGLETON and Spring beans are not thread safe. Is this assumption, correct?
  2. The EmployeeManager is defined part of the Servlet which can be accessed by multiple threads. Assume,"delete" method is called by multiple threads at the same time with values "1" "2" & "3" and same instance of EmployeeManager is generated for each thread(since its SINGLETON), which delete value will be executed.How Spring handles this condition?

    @Controller        
    public class EditEmployeeController
    {
    @Autowired
    private EmployeeManager employeeManager;
    
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String listEmployees(ModelMap map)
    {
        map.addAttribute("employee", new EmployeeEntity());
        map.addAttribute("employeeList", employeeManager.getAllEmployees());
        return "editEmployeeList";
    }
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addEmployee(@ModelAttribute(value="employee") EmployeeEntity employee, BindingResult result)
    {
        employeeManager.addEmployee(employee);
        return "redirect:/";
    }
    @RequestMapping("/delete/{employeeId}")
    public String deleteEmplyee(@PathVariable("employeeId") Integer employeeId)
    {
        employeeManager.deleteEmployee(employeeId);
        return "redirect:/";
    }
    public void setEmployeeManager(EmployeeManager employeeManager) {
        this.employeeManager = employeeManager;
    }
    }
    

EmployeeManager -

public interface EmployeeManager {
    public void addEmployee(EmployeeEntity employee);
    public List<EmployeeEntity> getAllEmployees();
    public void deleteEmployee(Integer employeeId);
}

@Service
public class EmployeeManagerImpl implements EmployeeManager
{
    @Autowired
    private EmployeeDAO employeeDAO;
    @Override
    @Transactional
    public void addEmployee(EmployeeEntity employee) {
        employeeDAO.addEmployee(employee);
    }
    @Override
    @Transactional
    public List<EmployeeEntity> getAllEmployees() {
        return employeeDAO.getAllEmployees();
    }
    @Override
    @Transactional
    public void deleteEmployee(Integer employeeId) {
        employeeDAO.deleteEmployee(employeeId);
    }
    public void setEmployeeDAO(EmployeeDAO employeeDAO) {
        this.employeeDAO = employeeDAO;
    }
}
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
user1050619
  • 19,822
  • 85
  • 237
  • 413
  • Maybe reading answer to http://stackoverflow.com/questions/11508405/are-spring-mvc-controllers-singletons will help. – Atul Nov 24 '14 at 08:30

3 Answers3

0
  1. Yes, your assumption is correct: if you do not declare a scope for your bean in Spring, it is a Singleton by default, which means it is not thread safe.

  2. By virtue of the assumption above being true, the short answer to your question is that Spring does not do anything to handle multithreading of a singleton bean, it is up to you to deal with thread safety and concurrency issues of that bean. The good news is that based on what your EmployeeManager bean does and the "1, 2, 3" scenario you outlined, it doesn't actually matter and you don't really have to do anything.

Here is the long answer as to why that is the case. Contrary to the common misconception, there is no such thing as multiple threads being truly executed at the same time. Sure, they may appear to be executing at the same time, but what's really happening under the hood is that the JVM takes one of the threads, executes a portion of it, then in the most efficient way (you would hope) starts working on another thread, then another, then maybe the first again, etc.

The reason why this doesn't even matter to you is because your bean does not have any state. In other words, you are just passing customer IDs, and you don't care which gets deleted first.

Now, if you were actually passing the SAME customer object in those threads, then you might have a problem. Bottom line is, the general rule of thumb is that any bean without state can be a singleton. You can read this article regarding Spring singletons and thread safety that explains that and much more in great detail.

Hope this helps.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
The Saint
  • 416
  • 3
  • 9
  • 1
    "Contrary to the common misconception, there is no such thing as multiple threads being truly executed at the same time" - this sounds wrong to me - can you provide a citation? In addition, the bean *does* have state, its just not mutable... – Gareth Aug 03 '16 at 13:15
  • 1
    @Gareth - You won't get a decent citation, because that statement is false. If you have a computer with multiple cores (and typical modern PC or server hardware falls into this category), then different threads in a JVM can literally be executing at the same time on different cores. – Stephen C Feb 25 '18 at 07:26
  • @Gareth - Apologies on the late reply-- I'm not much on Stack Overflow these days. The multithreading misconception I was referring to is called time-division multiplexing, which is a scheduling routine single-core processors use to mimic threads executing in parallel when they are actually not. Many people (like Stephen C) mistakenly think that with the advent of multi-core processors your Java threads are neatly distributed across those cores, but with thousands of other threads running on your OS, most of your Java threads are ending up on the same core, where multiplexing takes over. – The Saint Mar 27 '18 at 21:51
  • Btw, for a nice reference that explains all this, feel free to read the following: https://scalibq.wordpress.com/2012/06/01/multi-core-and-multi-threading/ – The Saint Mar 27 '18 at 21:53
  • Still your first point is quite confusing tho , maybe you are relating thread safety with the actual instance context / state ? Its like you are proposing making the beans prototypes or session bound , which still will have the same threading issue ........ Also your second point about running java in parallel is quite JVM specific. F.E. Some 64bit Linux JVM Builds , can even assign the thread to a specific Core....... – AntJavaDev Sep 28 '18 at 02:32
0

I agree with the above answer. Just wanted to emphasize that The only protection from race-conditions is the "@Transactional" bit, which means spring replaces your EmployeeManagerImpl with an instance that consults the transactionManager at the start/end of each method. Roughtly speaking :

public void addEmployee(EmployeeEntity employee) {
    transactionManager.startTransaction();
    employeeDAO.addEmployee(employee);
    transactionManager.endTransaction();
    // Just a rough outline; more accurately there should be 'finally' and rollback
}
...

Now if 2 threads access data at the same time, their behavior depends on your transactoinManager, transaction Isolation level, and how your DataSource interacts with it. In simple cases your thread will be forced to wait; on other cases the database could tolerate some concurrent access. That magic boils down to the transaction, not to spring. Also there is no control on threads before they reach the transaction. If 3 different threads ask to delete 1,2 and 3 you can't tell which one will get to 'startTransaction' first. But it shouldn't really matter - you might as well have a situation where someone asks to delete "2" on Sunday, someone else asks to delete "3" on Monday, and someone else asks to delete "1" on Tuesday. You just need a reasonable consistent end result.

Pelit Mamani
  • 2,321
  • 2
  • 13
  • 11
0

Spring scope singleton has nothing to do with thread safety those are two different concepts.

The difference between singleton & prototype bean is how we ask spring container that manages beans life-cycle to return beans:

  • Singleton: Insure every time you call the bean it return the same instance.
  • Prototype: Return new instance when ever called.

Calling bean can be trigger by either @autowirde or AppContext.getBean("beanName")

In summary it all depends on the objects injected the bean if it is not thread-safe then obviously it not gonna be thread-safe.

To learn more Spring Bean Scopes

Hussein Akar
  • 425
  • 3
  • 12