Reputation: 1405
Consider the following:
class A {
public static void main(String[] args) throws InterruptedException
{
final A a = new A();
new Thread()
{
public void run()
{
a.intrudeLock();
};
}.start();
Thread.sleep(1000);
new Thread()
{
public void run()
{
a.doSomethingAfterLocking();
};
}.start();
}
synchronized void doSomethingAfterLocking() throws InterruptedException
{
System.out.println("aquired lock");
Thread.sleep(10000);
System.out.println("finished stuff");
}
void intrudeLock()
{
System.out.println("don't need object's lock");
}
}
Going by the locking mechanism - the expected output is (at least in most of the cases):
aquired lock
don't need object's lock
finished stuff
I am not asking why this output, and understand the reason that the second thread doesn't require a lock for its method call and can thus intrude.
Now here is my doubt - When a thread acquires lock, its intention is gaining exclusivity over the object and intuitively the execution environment should prevent any state change by other threads. But this is not how Java implements it. Is there reason why this mechanism has been designed so?
Upvotes: 1
Views: 96
Reputation: 36304
When a thread acquires lock, its intention is gaining exclusivity over the object and intuitively the execution environment should prevent any state change by other threads. .
Small correction :
When a thread acquires lock, its intention is gaining exclusivity over the monitor of the object and intuitively the execution environment should prevent any state change by other threads which are waiting (which need) to acquire the same lock.*
Its completely left to the programmer to specify whether he wants some field / resource to be used only after acquiring a lock. If you have a field that can only be accessed by one thread, then it doesn't need synchronization (getting lock).
The important point that must be noted is that, it is completely left to the programmer to synchronize access to fields based on the code paths in the program. For example a field could be accessed by multiple threads in one code path (which calls for synchronization) and may be accessed by only one thread in another path. But since there is good probability that both the code paths can be accessed at the same time by different threads, you should acquire lock before entering any of the above mentioned code paths.
Now, the JIT may decide to ignore your lock requests (lock-elision) if it thinks that they are unnecessary (like trying to lock method local fields which never escape).
Upvotes: 1