reentrant lock when extending classes? - java

Given the following example:
this example is from "Java Concurrency in Practice".
there is a comment:
Because the doSomething methods in Widget and LoggingWidget are both synchronized, each tries to acquire the lock on the Widget before proceeding.
Why does the method doSomething in LoggingWidget class need to acquire the lock on the Widget? If it does, the synchronized on the method doSomething in LoggingWidget is useless, right?

Why does the method doSomething in LoggingWidget class need to acquire the lock on the Widget?
Assuming that you want to make sure that 2 threads can't run LoggingWidget#doSomething() concurrently (in this example, you may want to make sure that the object is not modified between the print statement and the call to super.doSomething()), then you need to make the method synchronized.
If you don't, a thread (T1) could start running LoggingWidget#doSomething() and print the object, another thread (T2) could then start running LoggingWidget#doSomething() too (the method is not synchronized) and print the object again, then T2 could run super.doSomething() which (let's say) changes the object, and then T1 would execute super.doSomething() but the state of the object would be different from what it printed because T2 has made changes in the meantime.
One way of preventing that is to make the method synchronized.
Because the doSomething methods in Widget and LoggingWidget are both synchronized, each tries to acquire the lock on the Widget before proceeding.
Reentrant means that a given thread can re-acquire a lock that it already holds. In this case, when a thread enters LoggingWidget#doSomething(), it acquires this because the method is synchronized. When it runs super.doSomething(), it needs to re-acquire the same lock. It intrinsic locks were not reentrant, the thread would block there forever, trying to acquire a lock that it already holds and that it will not release = deadlock.

Re-entrant lock will avoid duplicate by re acquiring lock on the object which already has been locked. Now, important thing is releasing lock will not release all the locks. JVM internally maintains counter which will be incremented each time lock is acquired on the object and decremented each time lock will be released. Thus, this mechanism not only avoid dead-lock but also maintains the correctness by keeping count.

Related

ReentrentLock on this object or super object [duplicate]

I was wondering if in Java I would get any odd behaviour if I synchronise twice on the same object?
The scenario is as follows
pulbic class SillyClassName {
object moo;
...
public void method1(){
synchronized(moo)
{
....
method2();
....
}
}
public void method2(){
synchronized(moo)
{
doStuff();
}
}
}
Both methods use the object and are synchronised on it. Will the second method when called by the first method stop because it's locked?
I don't think so because it's the same thread but I'm unsure of any other odd results that might occur.
Reentrant
Synchronized blocks use reentrant locks, which means if the thread already holds the lock, it can re-aquire it without problems. Therefore your code will work as you expect.
See the bottom of the Java Tutorial page Intrinsic Locks and Synchronization.
To quote as of 2015-01…
Reentrant Synchronization
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.
I think we have to use reentrant lock for what you are trying to do. Here's a snippet from http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html.
What do we mean by a reentrant lock? Simply that there is an acquisition count associated with the lock, and if a thread that holds the lock acquires it again, the acquisition count is incremented and the lock then needs to be released twice to truly release the lock. This parallels the semantics of synchronized; if a thread enters a synchronized block protected by a monitor that the thread already owns, the thread will be allowed to proceed, and the lock will not be released when the thread exits the second (or subsequent) synchronized block, but only will be released when it exits the first synchronized block it entered protected by that monitor.
Though I have not tried it, I guess if you want to do what you have above, you have to use a re-entrant lock.
Java appears to fully support nested locks on one object by the same thread. This means that if a thread has an outer and an inner lock on an object, and another thread tries to lock on the same object, the second thread will be suspended until both locks have been released by the first thread.
My testing was done under Java 6 SE.
No problems. In your example, (once you fix your code to get rid of the compile warnings that you'll get ;) ), the synchronization ensures that the blocks in method1 and method2 will not execute simultaneously.
That's kind of the point of synchronization. :)
Edit: Sorry, missed parts of your question, but Phill answered it. To summarize, a single thread cannot deadlock itself.
In java, the synchronized keyword on a method basically synchronizes on the current object, so in effect it's doing what you suggest above implicitly.
You won't experience problems with synchronizing on one object in one method and then synchronizing on the same object in another method because, as you say, the current thread already holds the lock on that object.
No, the second method will not stop if called by the first. No odd results will occur (Except a slight overhead for checking the lock. This won't matter much. From Java 6 onwards, you have lock coarsening in the JVM - Java SE 6 Performance White Paper.)
For example, take a look at source code of java.util.Vector. There are a lot of calls to other synchronized methods from within synchronized methods.

Why are wait while-loop conditions safe in a multithreaded context?

I have hard time to really understand, how that works:
while(<some condition>){
wait();
}
OR this example:
while(<some condition>){
condition.await();
}
When thread already passed the <some condition>,
it may really happen, that <some condition> already false when wait() or await() executed.
So wait() or await() may be called with already invalidated condition - that means the intention is broken.
What is wrong with my logic?
From the docs for wait():
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
(emphasis mine)
In other words, without a synchronized block, your code will throw an IllegalMonitorStateException. With synchronized, on the other hand, your condition will be checked atomically with the wait(); call.
This does not automatically mean you have no problems, because "atomically" here is only with regard to the object you're synchronizing on (in your case this), and only relative to other synchronized access to that object. If your condition depends on different objects, or you access the object without synchronization somewhere else, things might go bad. Thus, don't do that.
The same reasoning goes for the use of Locks and Conditions. See this code sample. Condition variables are derived from lock objects, and synchronized/wait/notify is analogous to lock;unlock/await/signal.
Waking up from Object#wait() or Condition#await() means reacquiring the associated lock. Presumably, <some condition> should only be modified when owning the lock. So if the thread that woke up now owns the lock, no other thread should be able to change the condition to false.

Java blocked methoded from another thread

If a method is blocked at the wait statement, can another thread call the method/will the print statement be executed?
Thanks
synchronised test() {
sysout("not blocked");
wait();
}
A common misconception is that the the method is locked. In fact the object this is locked. This means you can have the same method being called for different objects without using wait()
Conversely, if one thread obtains a lock, this will exclude any other locked section in any other method for this object.
A waiting thread releases the current lock so other methods can obtain a lock on the same object. This also means that thread must re-acquire the lock to stop waiting.

Synchronized on a monitor

I'm just trying to further my understanding of this concept.
We have a monitor, let's say a queue or a map of some sort. This monitor has methods to put objects on, and get objects off. In order to be thread safe, the monitor will lock on it's put methods and on it's get methods. When a thread is synchronized to this monitor, it's constantly trying to obtain this monitor's right's so it can proceed with what it needs to do. Does this sound right?
Another question, how does the flow of control work here. Which code is executed once the thread has gained access to the monitor? I'm finding it hard to debug multi-threaded programs with just print statements, it get's really messy and confusing.
public void run(){
try{
synchronized (monitor){
while (monitor is empty){
monitor.wait(); // Does this line pause the thread or the monitor?
}
System.out.println("Done Waiting");
}
System.out.println("Out of the synchronized block");
}
}
Here's the definition from the Java Language Specification:
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.
To answer
This monitor has methods to put objects on, and get objects off. In
order to be thread safe, the monitor will lock on it's put methods and
on it's get methods. When a thread is synchronized to this monitor,
it's constantly trying to obtain this monitor's right's so it can
proceed with what it needs to do. Does this sound right?
So you're not interacting with a monitor. A monitor doesn't have a concept of methods. Don't think of it like that. You interact with objects which have monitors. When a thread acquires an object's monitor, it doesn't need to constantly trying to obtain it, it already has it.
Another question, how does the flow of control work here. Which code
is executed once the thread has gained access to the monitor? I'm
finding it hard to debug multi-threaded programs with just print
statements, it get's really messy and confusing.
If execution enters the synchronized block on an object, the currently executing thread has acquired the monitor on the synchronized object, in this case the object referenced by the variable monitor.
I'll assume (thanks to Radiodeaf) that by monitor is empty, you mean your Map object doesn't have any entries.
When you call
monitor.wait();
the current thread releases the monitor on the object referenced by monitor and sleeps until it gets notified.
The javadoc of Object#wait() has more details.
So you will loop on the check for empty and wait if it returns true. We can assume that some other piece of code calls notify() when they put something into the Map.
When the object does get notified, the thread then has to compete to re-acquire the object's monitor. This is obviously necessary so that the thread can be executing inside a synchronized block on the object.
As we know We can call wait method only from synchronized context.
So By saying wait release the lock we mean that once lock is acquired on an object when it is in synchronized context , by calling wait method on same object , it release the lock and allow other thread to work on that object.

Method Synchronization

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?

Categories