All good explanations above. But I will give an example.
Think about this analogy (this is my original thinking
). A house has a main door and it has several rooms inside it, including a bathroom. Assume 5 people live in this house and all have the authority to enter/use it. What if one person wants to use the bathroom? He goes inside the room and locks the door. But this still allows the other 4 people to use all other rooms as they wish. The only thing they can't use is the bathroom (assuming there is only one!). So this is like synchronizing a small block of the code.......... But now think about this...what will happen if he locks the entire house i.e. the main door and not allow anyone into the house, even though he wants to only use the bathroom? Is that necessary or efficient? NO. Why? Because he locked the entire house when he didn't have to!!! Now everyone else has to wait outside in the bad weather and they are so annoyed
. This person could have only locked the bathroom and still allowed the other occupants to use all the other rooms. That would have been efficient!!! So here even though the entire house is shared, it is enough to lock only the bathroom when one wants to use it.
Synchronization is similar. Only synchronize the ABSOLUTE MINIMUM code you want and still allow other threads to execute the rest of the code, while one thread is executing the synchronized section. Otherwise it makes your code inefficient. Hope this makes it clear to you.