The main reason I would choose the second approach is because I do not control what clients do with instances of my class.
If for some reason someone decides to use an instance of my class as a lock, they will interfere with the synchronization logic in my class:
class ClientCode { Example exampleInstance; void someMethod() { synchronized (exampleInstance) {
If in my Example
class I use a lock that no one else sees, they cannot interfere with my logic and introduce an arbitrary mutex, as in the above scenario.
To summarize, this is just an application of the principle of information hiding.
source share