For example the following parallel execution:
methodA() calls syncMethod() then calls somethingElse()
methodB() calls syncMethod() then calls somethingElse()
methodB() calls syncMethod() then calls somethingElse()
What happens:
- methodA opens Transaction A enters syncMethod
- methodB opens Transaction B waits on syncMethod
- methodA exits syncMethod, starts executing somethingElse
- methodB enters syncMethod while methodA completes somethingElse and commits Transaction A
- methodB exits syncMethod, starts executing somethingElse
- methodB completes somethingElse and commits Transaction B
Now the important part is points 4. If the syncMethod requires fresh data from other executions, methodB will NOT see that data when it enters syncMethod since Transaction A has NOT yet been commited.
The synchronization is only blocking a thread from entering the protected code block, but as soon as the resource is free, the next waiting thread will enter immediately.
This means that to allow other methods to read latest data while in the protected section, any operation done in the synchronized method must be executed in a separate transaction, for example using the TransactionHandler helper.