Assume the following method:
public synchronized void a(){
try{
System.out.println("a");
return;
}finally{
System.out.println("a, finally");
}
}
I understand that the finally block will still be executed even after the return statement. One can even "override" the return value !
But my question is, will the method be unlocked after the return statement or after finally ?
Since return is not executed before finally block has finished, and because the entire method is synchronized, the lock is not released until after the finally block has finished.
If you need to release the lock on exception rather than on returning from the method, you can nest your synchronized block inside the try/finally block:
public void a(){
try {
synchronized (this) {
System.out.println("a");
return;
}
} finally{
System.out.println("a, finally");
}
}
1st of all finally will execute before the return statement....
Secondly the lock will be released only when the thread has finished executing the complete method.. ie(till the end braces of this method), Moreover this lock is of the object, so not only this method, but all the synchronized method in that class are locked.
yes it is. It'll wait up to return from function which happen after executing finally block execution.
Related
I am a bit confused about synchronized-blocks in Java.
If one thread enters a synchronized-block of an instance of a class, can other threads use synchronized-methods of the same instance of the same class?
void myMain() {
synchronized(this) {
while(suspendFlag)
wait();
}
}
}
synchronized void mysuspend() {
suspendFlag = true;
}
synchronized void mysuspend(){
suspendFlag = true;
}
is equivalent to
void mysuspend(){
synchronized(this) {
suspendFlag = true;
}
}
So in your code it is not possible that one thread enters a synchronized block of an instance of a class and other threads use synchronized method mysuspend()
Yes, because they are independently callable.
A thread is not attached to a class or an instance of it. Each method of a class may be called independently from different threads.
What can limit this independence are synchronized methods. They are shortcuts for synchronized(this) {...} as method body.
Whenever a synchronized block is entered, the monitor on the associated instance is held.
A wait() frees the monitor on the surrounding synchronized block again, so other synchronized blocks can be executed.
There is a problem with your code: wait() will wait until a notify() on the monitor is called. But in your code neither a notify() is called, nor has the wait() a timeout.
Your while(suspendFlag) wait(); will then wait forever...
I have this piece of code:
Profile a = randomProfile();
Thread workerA = new Thread(new Downloader(a));
workerA.start();
Profile b = randomProfile();
Thread workerB = new Thread(new Downloader(b));
workerB.start();
synchronized (workerA) {
try {
workerA.wait();
} catch (InterruptedException e) {
System.out.println("Error on background thread!");
System.exit(1);
}
}
synchronized (workerB) {
try {
workerB.wait();
} catch (InterruptedException e) {
System.out.println("Error on background thread!");
System.exit(1);
}
}
And a Downloader class which implements the Runnable interface, and its run() method looks like:
#Override
public void run() {
synchronized (this) {
//work...
notify();
}
}
Now this is working as intented, sometimes. Most of the time though, it seems to get stuck in the second synchronized block (it always gets through the first one).
Am I doing something wrong?
Also do I have some conceptual error, e.g. this implementation doesn't give me any advantage over a single thread?
The wait() is invoked on the Thread objects but the notify() is invoked on the Downloader objects.
The background threads should therefore run without a problem (although completely unsynchronized), and the main thread should always block to infinity in the first synchronized block because there's no-one to wake it up.
Where this case is special is that you invoked wait() on the Thread objects themselves, which is discouraged (and by this I really mean: forbidden). When a thread terminates, it invokes notifyAll() on itself, so when workerA finishes, you get out of the first synchronized block. But by the time the second synchronized block is reached, workerB is already finished, so the second wait() will never end.
Whether there is a conceptual error depends on what you were trying to achieve. From the code it looks very much like what you tried to do is join() the background threads.
I'm developing an Android app.
I have two threads. The first one has to wait the second one.
I have this code on the first thread run method:
#Override
public void run() {
synchronized (this.secondThread) {
this.secondThread.wait();
}
[...]
}
And on my second thread:
#Override
public void run() {
synchronized (MyClass.myLock) {
try {
// Do something important here
}
catch (Exception ex)
{
// manage exception
return;
}
finally {
// do something...
}
}
synchronized (this) {
this.notify();
}
[...]
}
As you can see, there is a return inside catch block.
With this code, will first thread get notified if an exception occurs on the second thread?
will first thread get notified if an exception occurs on the second
thread?
Answer is no. Unless you explicitly notify() in catch block before returning, the other thread will not wake up
Answer is no. In order to get both notify the has to be synchronized on the same object. this can be different. If you want all the thread waiting on a object to be notify you havo to call notifyAll() instead of notify(). The notifyAll() should be put inside the finally block. Infact despite the return the finally block is alway executed
The notify() should be inside the finally block if you want it to work unconditionally, but you should really be using Thread.join() instead of wait(): then the thread being waited on doesn't have to do anything at all.
Answer is no. Unless you explicitly notify() in catch block before returning, the other thread will not wake up, You have to Al possible exceptions and in every case notify to your first thread, make sure that your first thread input is not dependent on second thread output otherwise you may phase some other problem in thread 1.
In a Java try{} ... catch{} ... finally{} block, code within the finally{} is generally considered "guaranteed" to run regardless of what occurs in the try/catch. However, I know of at least two circumstances under which it will not execute:
If System.exit(0) is called; or,
if an Exception is thrown all the way up to the JVM and the default behavior occurs (i.e., printStackTrace() and exit)
Are there any other program behaviors that will prevent the code in a finally{} block from executing? Under what specific conditions will the code execute or not?
EDIT: As NullUserException pointed out, the second case is actually not true. I thought it was because the text in standard error printed after that in standard out, preventing the text from being seen without scrolling up. :) Apologies.
If you call System.exit() the program exits immediately without finally being called.
A JVM Crash e.g. Segmentation Fault, will also prevent finally being called. i.e. the JVM stops immediately at this point and produces a crash report.
An infinite loop would also prevent a finally being called.
The finally block is always called when a Throwable is thrown. Even if you call Thread.stop() which triggers a ThreadDeath to be thrown in the target thread. This can be caught (it's an Error) and the finally block will be called.
public static void main(String[] args) {
testOutOfMemoryError();
testThreadInterrupted();
testThreadStop();
testStackOverflow();
}
private static void testThreadStop() {
try {
try {
final Thread thread = Thread.currentThread();
new Thread(new Runnable() {
#Override
public void run() {
thread.stop();
}
}).start();
while(true)
Thread.sleep(1000);
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testThreadInterrupted() {
try {
try {
final Thread thread = Thread.currentThread();
new Thread(new Runnable() {
#Override
public void run() {
thread.interrupt();
}
}).start();
while(true)
Thread.sleep(1000);
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testOutOfMemoryError() {
try {
try {
List<byte[]> bytes = new ArrayList<byte[]>();
while(true)
bytes.add(new byte[8*1024*1024]);
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testStackOverflow() {
try {
try {
testStackOverflow0();
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testStackOverflow0() {
testStackOverflow0();
}
prints
finally called after java.lang.OutOfMemoryError: Java heap space
finally called after java.lang.InterruptedException: sleep interrupted
finally called after java.lang.ThreadDeath
finally called after java.lang.StackOverflowError
Note: in each case the thread kept running, even after SO, OOME, Interrupted and Thread.stop()!
Infinite loop in the try block.
Corrupt RAM? Program no longer runs as written? I've actually debugged that once on a DOS machine.
Testing the finally block in different statement in try block.
public static void main(String [] args){
try{
System.out.println("Before Statement");
/*** Statement ***/
System.out.println("After Statement");
}
catch(Exception e){
}
finally{
System.out.println("Finally is Executed");
}
Statements in which finally block is executed are following:
Thread.currentThread().interrupted();
Thread.currentThread().destroy();
Thread.currentThread().stop();
Thread.sleep(10);
Thread.currentThread().interrupt();
Runtime.getRuntime().addShutdownHook(Thread.currentThread());
If there is any exception occurred.
If there is no exception.
Statements in which finally block is not executed are following:
Thread.currentThread().suspend();
System.exit(0);
JVM crashed.
Power to CPU chip goes off.
OS kills JVM process.
Runtime.getRuntime().exit(0);
Runtime.getRuntime().halt(0);
There is a chance of partial execution when finally itself throws an exception (or leads to an error)
One could be "A finally is a part of daeomon thread it may not be executed".
The only times finally won't be called are:
if the power turns off
if you call System.exit()
if the JVM crashes first
if there is an infinite loop in the try block
if the power turns off
I think when JVM exits suddenly due to any reason, that can be a cause the control will not enter into the the finally block and never execute.
You can make it a part of Daemon Thread. You may use the method setDaemon(boolean status) which is used to mark the current thread as daemon thread or user thread and exit the JVM as and when required. This will enable you exit the JVM before finally{} is executed.
Another possible instance of a finally block never executing would be due to a design where the method returned before the try block was entered, as in the cases of some very bad code I've seen from time to time:
public ObjectOfSomeType getMeAnObjectOfSomeType() throws SomeHorrendousException {
if (checkSomeObjectState()) {
return new ObjectOfSomeType();
}
try {
// yada yada yada...
} catch (SomeHorrendousException shexc) {
// wow, do something about this horrendous exception...
} finally {
// do some really important cleanup and state invalidation stuff...
}
I know none of you would ever do this, so I hesitated to add this as a possible scenario, but thought, eh, it's Friday, what the heck ; )
Could you tell me if I should release lock before await on condition?
try {
lock.lock();
while (isNotEmpty()) {
condition.await();
}
} finally {
lock.unlock();
}
Or
try {
lock.lock();
while (isNotEmpty()) {
lock.unlock();
condition.await();
}
} finally {
lock.unlock();
}
No, you do not need to explicitly release the lock before calling await, await will release it automatically. From javadoc:
The lock associated with this Condition is atomically released and the
current thread becomes disabled for thread scheduling purposes[...]
And:
The current thread is assumed to hold the lock associated with this Condition when this method is called.
You can only await() on a Condition when you have lock()ed the associated Lock
Why don't you have a condition for isEmpty to make your conditions clearer.
See the example in the Javadoc. http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html
e.g.
lock.lock();
try {
while (count > 0)
isEmpty.await();
// do something when empty.
} finally {
lock.unlock();
}
wait and notify must be called from with in the synchronized block, so the same rule applies for await and signal. Though await releases automatically, but if you do it should be between lock() and unlock()
lock.lock() // start of synchronized block
condition.await()
lock.unlock() // end of synchronized block