The main reason why I would choose the 2nd approach is that I do not control what the clients do with the instances of my class.
If, for some reason, somebody decides to use an instance of my class as a lock, they will interfere with the synchronization logic within my class:
class ClientCode {
Example exampleInstance;
void someMethod() {
synchronized (exampleInstance) {
//...
}
}
}
If, within my Example
class, I'm using a lock that no one else can see, they cannot interfere with my logic and introduce an arbitrary mutex like in the above scenario.
To sum up, this is just an application of the information hiding principle.