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.
Related
I've a simple question but couldn't manage to find a proper answer. Imagine we have;
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}
What about the code after sync. block here? I mean sync. blocks are used to reduce scope of lock but here the code after it ( namelist.add(name) ) will be blocked, right ?
Assume thread A called this function above but it's gonna wait for 'this' lock to be released by thread B which had the lock before on some other method. Now, I wondered if the execution will resume from B's nameList.add(name) method while thread A is waiting on 'this' lock object - since nameList.add(name) is not in the sync block.
Now, I wondered if the execution will resume from B's nameList.add(name) method while thread A is waiting on 'this' lock object - since nameList.add(name) is not in the sync block.
No, the thread executing the method can't just skip over the block and execute the remaining part of the method. What it will do is block until it can acquire the monitor on this, then execute the synchronized block, then release the monitor on this, then add the string to the nameList.
If concurrent threads execute this, there's no guarantee of which threads will insert into the nameList first. It's possible that between the time that a thread releases the monitor on this and the time that it adds to the nameList one or more other threads might barge in and add to the list.
Also whatever nameList is implemented as needs to be a thread-safe collection, so that concurrent changes don't cause errors and so that changes are visible across threads. If nameList is an ArrayList or a HashSet, for instance, then this would not be safe.
In principle, keyword synchronized does following two things:
Code guarded by the synchronized keyword cannot be executed
simultaneously by more than one thread;
.. it controls the visibility of data (variables) between threads;
In your example, the code which is not in synchronized scope would be accessible by all other Threads which call this method;
Assuming the operations which is out of scope is writing operation, you'd (generally) want it to be synchronized to reduce any anomalies which may creep up.
synchronized(this) will block if and while another thread is inside this block. If the thread leaves this block, one waiting thread has a chance (amongst other waiting threads) to enter the block. namelist.add() is executed outside the synchronized scope, so it may be executed in parallel with other threads.
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'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.
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.
What is the usage of synchronized statements?
These are used for when you are building a program with many "threads". When main starts, it starts with one thread, which executes the steps in a sequence. You can start many more threads, which can then execute code at the same time. If you're executing the same code at the same time, things might behave in ways you don't want:
y = x+20;
// at this moment, before the next instruction starts, some other thread performs
// the above step, which sets 'y' (an object property) to something different.
int b = y+10; // this would not be x+20, as you might expect.
What you want to do is put a 'lock' over this block of code, to make sure that no other thread can start executing any code that is "synchronized on" the variable y.
synchronized (y) {
y = x+20;
int b = y+10;
} // lock gets released here
Now, all other threads have to wait for whichever thread got there first to exit the block and release the lock, at which point another thread grabs the lock, enters the block of code, executes it, and releases the lock. Note that y has to be an object (Integer), not a primitive type.
You can also add 'synchronized' to methods, which synchronizes on 'this' (the instance object), or the class in the case of a static method.
Writing multi-threaded code is hard, because of problems like this. Synchronization is one tool, though it has one major problem - deadlocks. There is a lot of information online about deadlocks.
It is a java built in form of mutual exclusion. This is used for multithreaded applications.
Sun concurrency tutorial
This has a section about synchronized, but you should read the whole thing if you are trying to use multithreaded applications.
Wiki mutex
It creates a section of code which, with respect to two or more threads, can (a) only be executed by one thread at a time, and (b) forms a memory barrier.
While understanding the concept of mutual-exclusion preventing concurrent execution of the code is quite easy, equally important is the memory barrier.
A memory barrier forms a "happens before" relationship between two threads. Any changes to memory made by a thread before acquiring a lock is guaranteed to be observed by another thread after it acquires the same lock. Due to the effects of CPU caches and their interaction with main memory, this is critical to preventing observation and update of stale cached memory and preventing race conditions between threads.
Only 1 thread at a time can access a synchronized block.
This is a basic language construct. If you're not at all familiar with it you'll need to review.
Invoking a synchronized instance method of an object acquires a lock on the object, and invoking a synchronized static method of a class acquires a lock on the class. A synchronized statement can be used to acquire a lock on any object, not just this object, when executing a block of the code in a method. This block is referred to as a synchronized block. The general form of a synchronized statement is as follows:
synchronized (expr) {
statements;
}
The expression expr must evaluate to an object reference. If the object is already locked by another thread, the thread is blocked until the lock is released. When a lock is obtained on the object, the statements in the synchronized block are executed, and then the lock is released.