As per Oracle docs for Intrinsic Locks and Synchronization :
Intrinsic locks play a role in both aspects of synchronization:
enforcing exclusive access to an object's state and establishing
happens-before relationships that are essential to visibility.
My question is:
what does happens-before relationships here means in synchronization context? Does this mean that once a thread executes a synchronized block all the changes are flushed to main memory before other thread comes and reacquire the lock?
Also I have another question:
Suppose thread1 has acquired the lock and is executing the synchronized block.
Is it possible for JVM/thread scheduler to force the thread1 to another state say wait such that it will release the lock and another thread say thread2 will acquire the lock? Now after some time thread1 can again go into running state and start from where it lost the lock.
what does happens-before relationships here means in synchronization
context?
This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement. In this case, it means when you write some thing in the synchronized block, then other threads which enter the synchronized block will notice this change.
Is it possible for JVM/thread scheduler to force the thread1 to
another state say wait such that it will release the lock and another
thread say thread2 will acquire the lock?
No, while the thread can release the lock by calling wait.
Related
Is it possible for the thread scheduler to unschedule a thread holding the lock to a synchronized block and is in the middle of executing it? If yes then does the unscheduling leads to thread releasing the lock? Assume thread doesn't call method such as wait/yield etc.
I have been trying to understand how synchronized block helps in read-update-write operation? If the thread which enters the synchronized block can't be unscheduled then it's easier to understand but if it can be then the issue of visibility comes as it might be the case that variable has been updated but not written to the main memory by thread and thread scheduler unschedules it and other thread gets the lock and updated the variable in the main memory.
Is there any info. in JLS regarding the same?
Is it possible for the thread scheduler to unschedule a thread holding [a lock]?
Yes, that can happen preemptively in many scheduling algorithms. It must happen if the thread makes a blocking system call (e.g., to wait for input).
If yes then does the unscheduling leads to thread releasing the lock?
Absolutely not! That would defeat the purpose of locking, and it would break most multi-threaded programs.
Takeaway: Keep your critical sections as short as possible! Don't let threads B, C, D, and E all get blocked waiting for thread A to release some lock when thread A is blocked performing a long computation (or worse, waiting for input).
void method1() {
synchronized(this) { // Acquires intrinsic lock
method2();
}
}
void method2() {
synchronized(this) {} // Acquires same lock due to Reentrant synchronization
}
First time lock is acquired in method1 which calls synchronized method2 where second time it gets the same lock .
Now my doubt is when synchronized block ends in method2() does unlocking happens here first time and returns to synchronized block of method1() where again unlocking happens second time .
Does it internally manages count of locks like in ReentrantLock ?
Does it internally manages count of locks like in ReentrantLock ?
Yes. From JLS section 17.1 - emphasis mine.
The Java programming language provides multiple mechanisms for communicating between threads. The most basic of these methods is synchronization, which is implemented using monitors. Each object in Java is associated with a monitor, which a thread can lock or unlock. Only one thread at a time may hold a lock on a monitor. Any other threads attempting to lock that monitor are blocked until they can obtain a lock on that monitor. A thread t may lock a particular monitor multiple times; each unlock reverses the effect of one lock operation.
Yes internally jdk keeps track of reentrance.
As per oracle docs:
Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.
See this for details.
I was reading Java Concurrency in Practice.
SO it is written that
When thread A executes a synchronized block, and subsequently thread B enters a
synchronized block guarded by the same lock
How can two thread take lock on same object at a time?
Thanks.
"When thread A executes a synchronized block, and subsequently thread B enters a
synchronized block guarded by the same lock" .
There will only be one lock. Thread B can get hold of the lock only when Thread A releases the lock. "subsequently". The author wants to say that the changes made by Thread A on the same object will be visible to Thread B.
They mean B enters lock after A released it
Each object has lock. Just before a thread enters the synchronized block to execute the code, it acquires the lock. When the thread has finished executing the block, it releases the lock. The second thread cannot acquire the lock during this time. It acquires the lock once it has been released by the first thread.
What happens, when two threads try to access a synchronized block?
Will one of the threads be queued somewhere and access the thread later, or will the thread give up if the trial fails?
Assuming you mean a synchronized block, one thread will manage to acquire the monitor, and the other thread will block until the monitor is released.
See section 14.19 and section 17.1 of the JLS for more details, including:
The synchronized statement (ยง14.19) computes a reference to an object; it then attempts to perform a lock action on that object's monitor and does not proceed further until the lock action has successfully completed. After the lock action has been performed, the body of the synchronized statement is executed. If execution of the body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same monitor.
(Emphasis mine.)
If you need any other semantics - e.g. timeouts - you should use one of the the types in the java.util.concurrent.locks package, so that you can use methods such as tryLock() and tryLock(long time, TimeUnit unit).
Will one of the threads be queued somewhere
Yes, It's queued in JVM and waits until runnig thread frees the lock.
will the thread give up if the trial fails
No, it keeps on trying till JVM is alive. but not trying during while another thread in running the synchronized code.(unless a timeout is specified)
Lets say ThreadA and ThreadB are trying for a synchronized block sb and ThreadB succeeds. Now, ThreadA will wait till ThreadB finishes. in the mean time, suppose ThreadC comes for sb. it sees that the block is being run by some thread and waits in same queue with ThreadA. When ThreadB finishes either ThreadA or ThreadC is given a chance to execute.
So, technically, it's NOT a queue but a similar datastructure.
One of them will wait, forever if necessary (such as the first thread executing an infinite loop), though that would be a rather bad design. There are no timeouts on code execution synchronisation.
From the JLS:
A synchronized statement acquires a mutual-exclusion lock on behalf of the executing thread, executes a block, then releases the lock. While the executing thread owns the lock, no other thread may acquire the lock.
If synchronized block is being executed by another thread then both thread will wait. Otherwise , one thread will be allowed to work upon and another will wait until first thread completes its job.
When we declare a method synchronized then how it is known by second thread that the synchronized section of code used by the first thread is completed and how second thread can use that synchronized section of code?
The thread scheduler tells the second thread. When a thread exits a synchronized block stuff happens in this order:
The exiting thread releases its lock.
The lock tells the thread scheduler that it was released.
The thread scheduler changes the state of the threads waiting on that lock to "running".
The running threads race to acquire the lock, one of them wins, the rest go back to waiting.
The scheduler decides which threads to run and what order to run them in and when to context-switch, so it influences which thread gets the lock, but it doesn't directly hand the lock over to the next thread in line. (Who knows, maybe some implementation does, but you can't count on that behavior in general.)
Java uses an internal construct called a monitor to manage synchronization, basically when thread 1 enters a synchronized method, it takes control of the monitor, similarly when it is finished it releases the monitor. Any threads that arrive while the monitor is currently held are blocked until the monitor is released. Then they enter the synchronized method.
here is more information on monitors:
http://en.wikipedia.org/wiki/Monitor_(synchronization)
When it is a non-static method then this is equivalent synchronizing over this:
public synchronized void xyz() { ... }
is equivalent to
public void xyz() {
synchronized(this) {
...
}
}
When it is a static method then it is synchronized over class object instead.
When thread A enters synchronized method, It acquires a LOCK on the Object calling the method, so any other Thread cannot call the synchronized method using that particular object. However any Thread B can call that synchronized method using some other object of the same class.
So once Object is Locked, No thread can call synchronized method using that object until The previous thread release the Lock. and previous thread will release the lock when it has finished executing the synchronized method.
In the mean time if Thread B and Thread C have invoked the same synchrinized method using the same previous object, then they will start waiting for Thread A to release Lock on Object. When Thread A will release Lock on the Object, then Thread B OR Thread C can start executing, There is no guarantee which one will go first. The other one will continue waiting.
Have a look at oracle documentation page to understand concepts clearly.
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.
Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them.
A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
Javaword article by Bill Venners clearnly explains what actually happening under the hoods.
Two opcodes, monitorenter and monitorexit, are used for synchronization blocks
When monitorenter is encountered by the Java virtual machine, it acquires the lock for the object referred to by objectref on the stack. If the thread already owns the lock for that object, a count is incremented.
Each time monitorexit is executed for the thread on the object, the count is decremented. When the count reaches zero, the monitor is released.
Once the monitor is released, one of the waiting threads will acquire the monitor and above process will be repeated again.
Have a look at related SE questions:
What does 'synchronized' mean?
How Synchronization works in Java?