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.
Related
Let's say you have two threads, thread1 and thread2. If you call thread1.start() and thread2.start() at the same time and they both print out numbers between 1 and 5, they will both run at the same time and they will randomly print out the numbers in any order, if I am not mistaken. To prevent this, you use the .join() method to make sure that a certain thread gets executed first. If this is what the .join() method does, what is the Lock object used for?
Thread.join is used to wait for another thread to finish. The join method uses the implicit lock on the Thread object and calls wait on it. When the thread being waited for finishes it notifies the waiting thread so it can stop waiting.
Java has different ways to use locks to protect access to data. There is implicit locking that uses a lock built into every Java object (this is where the synchronized keyword comes in), and then there are explicit Lock objects. Both of them protect data from concurrent access, the difference is the explicit Locks are more flexible and powerful, while implicit locking is designed to be easier to use.
With implicit locks, for instance, I can't not release the lock at the end of a synchronized method or block, the JVM makes sure that the lock gets released as the thread leaves. But programming with implicit locks can be limiting. For instance, there aren't separate condition objects so if there are different threads accessing a shared object for different things, notifying only a subset of them is not possible.
With explicit Locks you get separate condition objects and can notify only those threads waiting on a particular condition (producers might wait on one condition while consumers wait on another, see the ArrayBlockingQueue class for an example), and you can implement more involved kinds of patterns, like hand-over-hand locking. But you need to be much more careful, because the extra features introduce complications, and releasing the lock is up to you.
Locking typically prevents more than one thread from running a block of code at the same time. This is because only ONE thread at a time can acquire the lock and run the code within. If a thread wants the lock but it is already taken, then that thread goes into a wait state until the lock is released. If you have many threads waiting for the lock to be released, which one gets the lock next is INDETERMINATE (can't be predicted). This can lead to "thread starvation" where a thread is waiting for the lock, but it just never gets it because other threads always seem to get it instead. This is a very generic answer because you didn't specify a language. Some languages may differ slightly in that they might have a determinate method of deciding who gets the lock next.
The first question is simple.
Say Java runtime has encountered three synchronized blocks with the same lock.
It sees bloc one first and grabs the lock and meanwhile it is running it encounters block two first and three next and both fail to obtain the lock.
Now block one finished and releases the lock so does this guarantee that block two will be the one to grab the lock and execute first since it tried to grab the lock before block three?
Next, say we have a method that has two synchronized blocks. Is it possible that block 1 which comes before block 2 might be reordered to run after block 2?
In the case they share the same lock, I am guessing the answer is no, but that might be wrong. Also what if they do not share the same lock?
synchronized blocks do not provide fairness guarantees which means that if thread A acquired lock and then threads B and C are waiting for the same lock there is no guarantee which of them will first acquire lock when thread A releases it.
Also JIT compiler could decide to merge adjacent synchronized blocks which use the same lock object. Also JIT could remove synchronization if no other thread will ever use it like this
synchronized (new Object()) {}
https://www.ibm.com/developerworks/java/library/j-jtp10185/
I read this in an upvoted comment on StackOverflow:
But if you want to be safe, you can add simple synchronized(this) {}
at the end of you #PostConstruct [method]
[note that variables were NOT volatile]
I was thinking that happens-before is forced only if both write and read is executed in synchronized block or at least read is volatile.
Is the quoted sentence correct? Does an empty synchronized(this) {} block flush all variables changed in current method to "general visible" memory?
Please consider some scenerios
what if second thread never calls lock on this? (suppose that second thread reads in other methods). Remember that question is about: flush changes to other threads, not give other threads a way (synchronized) to poll changes made by original thread. Also no-synchronization in other methods is very likely in Spring #PostConstruct context - as original comment says.
is memory visibility of changes forced only in second and subsequent calls by another thread? (remember that this synchronized block is a last call in our method) - this would mark this way of synchronization as very bad practice (stale values in first call)
Much of what's written about this on SO, including many of the answers/comments in this thread, are, sadly, wrong.
The key rule in the Java Memory Model that applies here is: an unlock operation on a given monitor happens-before a subsequent lock operation on that same monitor. If only one thread ever acquires the lock, it has no meaning. If the VM can prove that the lock object is thread-confined, it can elide any fences it might otherwise emit.
The quote you highlight assumes that releasing a lock acts as a full fence. And sometimes that might be true, but you can't count on it. So your skeptical questions are well-founded.
See Java Concurrency in Practice, Ch 16 for more on the Java Memory Model.
All writes that occur prior to a monitor exit are visible to all threads after a monitor enter.
A synchronized(this){} can be turned into bytecode like
monitorenter
monitorexit
So if you have a bunch of writes prior to the synchronized(this){} they would have occurred before the monitorexit.
This brings us to the next point of my first sentence.
visible to all threads after a monitor enter
So now, in order for a thread to ensure the writes ocurred it must execute the same synchronization ie synchornized(this){}. This will issue at the very least a monitorenter and establish your happens before ordering.
So to answer your question
Does an empty synchronized(this) {} block flush all variables changed
in current method to "general visible" memory?
Yes, as long as you maintain the same synchronization when you want to read those non-volatile variables.
To address your other questions
what if second thread never calls lock on this? (suppose that second
thread reads in other methods). Remember that question is about: flush
changes to other threads, not give other threads a way (synchronized)
to poll changes made by original thread. Also no-synchronization in
other methods is very likely in Spring #PostConstruct context
Well in this case using synchronized(this) without any other context is relatively useless. There is no happens-before relationship and it's in theory just as useful as not including it.
is memory visibility of changes forced only in second and subsequent
calls by another thread? (remember that this synchronized block is a
last call in our method) - this would mark this way of synchronization
as very bad practice (stale values in first call)
Memory visibility is forced by the first thread calling synchronized(this), in that it will write directly to memory. Now, this doesn't necessarily mean each threads needs to read directly from memory. They can still read from their own processor caches. Having a thread call synchronized(this) ensures it pulls the value of the field(s) from memory and retrieve most up to date value.
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.
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.