From the Java java.util.concurrent.Semaphore docs it wasn't quite clear to me what happens if semaphore.acquire() blocks the thread and later gets interrupted by an InterruptedException. Has the semaphore value been decreased and so is there a need to release the semaphore?
Currently I am using code like this:
try {
// use semaphore to limit number of parallel threads
semaphore.acquire();
doMyWork();
}
finally {
semaphore.release();
}
Or should I rather not call release() when an InterruptedException occurs during acquire() ?
call release() when an InterruptedException occurs during acquire() ?
You should not. If .acquire() is interrupted, the semaphore is not acquired, so likely should not release it.
Your code should be
// use semaphore to limit number of parallel threads
semaphore.acquire();
try {
doMyWork();
}
finally {
semaphore.release();
}
nos's accepted answer is partially correct, except semaphore.acquire() also throws InterruptedException. So, to be 100% correct, the code would look like:
try {
semaphore.acquire();
try {
doMyWork();
} catch (InterruptedException e) {
// do something, if you wish
} finally {
semaphore.release();
}
} catch (InterruptedException e) {
// do something, if you wish
}
If the thread is interrupted before acquire method call, or while waiting to acquire a permit the InterruptedException will be thrown and no permit will be hold, so no need to release. Only when you are certain that a permit was acquired (after calling the acquire method call) you will need to release the permit. So you better acquire before your try block starts, something like:
sem.acquire();
try{
doMyWork();
}finally{
sem.release();
}
Related
I'm reading J. Bloch's Effective Java and now I'm at the section which explains about Concurrency. The writer has provided the following example (Some modifications were applied to make it simpler):
Runnable action;
//...
executor.execute(new Runnable() {
public void run() {
ready.countDown();
try {
start.await();
action.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // <------- Here
} finally {
done.countDown();
}
}
});
It's not clear that why we interrupt the Thread that already was interrupted? Couldn't you get a little explanation about what kind of troubles we may run into if we omit such interrupting?
Yes, it's right.
When an InterruptedException is thrown from a blocking method, the interrupt flag is cleared.
The right thing to do is to reset the interrupt flag (i.e. interrupt again) and stop running ASAP. Resetting the interrupt flag is necessary to let the executor (or any other calling code) know that the thread has been interrupted, and thus allow it to stop running.
This question already has answers here:
Threads - Why a Lock has to be followed by try and finally
(6 answers)
Closed 8 years ago.
I'm not sure whether the following implementation is correct. My reason is that if the current thread is interrupted while it is waiting to be signaled, the finally block will be called, but because it's not holding the lock, an IllegalMonitorStateException will be thrown. Did I implement a try-finally block correctly in this case or rather should one be implemented?
public void acquire() throws InterruptedException {
try {
lock.lockInterruptibly();
while (permits == 0) {
condition.await();
}
permits--;
}
finally {
lock.unlock();
}
}
Not sure that I understand problem correctly, but you should try-finally only after the resource is allocated
public void acquire() throws InterruptedException {
lock.lockInterruptibly(); // allocate resource before try
try {
while (permits == 0) {
condition.await();
}
permits--;
}
finally {
lock.unlock();
}
}
I do not know why do all schools, e.g. Sun's official page on finally, advise allocating inside the try (so that you need if(allocated) {release}) in the finally clause. This is stupid IMO. Why does everybody advise allocation inside try?
A good question. I was actually surprised by the result myself.
If an InterruptedException occurs the condition will stop awaiting and will then execute the finally. It will obvious not own the lock and propagate an IllegalMonitorStateException.
How about this solution?
public void acquire() throws InterruptedException {
lock.lockInterruptibly();
while (permits == 0) {
condition.await();
}
try {
permits--;
}
finally {
lock.unlock();
}
}
When await returns, the current thread will have the lock. If it gets interrupted while it is waiting to be signaled by other threads (i.e. it does not have the lock), acquire will throw the InterruptedException back up to the caller.
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
I want to interrupt a thread, but invoking interrupt() doesn't seem to work. Below is the sample code:
public class BasicThreadrRunner {
public static void main(String[] args) {
Thread t1 = new Thread(new Basic(), "thread1");
t1.start();
Thread t3 = new Thread(new Basic(), "thread3");
Thread t4 = new Thread(new Basic(), "thread4");
t3.start();
t1.interrupt();
t4.start();
}
}
class Basic implements Runnable{
public void run(){
while(true) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.err.println("thread: " + Thread.currentThread().getName());
//e.printStackTrace();
}
}
}
}
but the output looks like thread 1 is still running. Can anyone explain this as well as how interrupt() works? Thanks!
The thread is still running simply because you catch InterruptedException and keep running. interrupt() primarily sets a flag in the Thread object, which you can check with isInterrupted(). It also causes some methods -- sleep(), join Object.wait(), in particular -- to return immediately by throwing an InterruptedException. It also causes some I/O operations to immediately terminate. If you're seeing the printouts from your catch block, then you can see that interrupt() is working.
As others have said, you catch the interrupt, but do nothing with it. What you need to do is propagate the interrupt using logic such as,
while(!Thread.currentThread().isInterrupted()){
try{
// do stuff
}catch(InterruptedException e){
Thread.currentThread().interrupt(); // propagate interrupt
}
}
Using looping logic, such as while(true) is just lazy coding. Instead, poll the thread's interrupted flag in order to determine termination via interruption.
++1, in addition to other answers. I believe the misconception about this was that it seemed the try/catch block finished its job after the Thread.sleep(1000); call i.e. try to sleep for 1000ms, catch anything that might interrupt my sleep attempt.
What is happening actually is that the try/catch block is still very much active while sleeping i.e. try to sleep for 1000ms, catch anything that might interrupt during my sleep
Hence the reason why the exception is being caught immediately (and afterwards) since the thread barely just started its sleep.
The Java documentation is not clear on this point. What happens if you call interrupt on a Thread before a call to Thread.sleep():
//interrupt reaches Thread here
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
return;
}
Will the InterruptedException be thrown?
Please point to relevant documentation.
Yes, it will throw an exception. According to the javadoc for Thread.sleep, the method:
Throws:
InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
The 'has' in this case is an informal way of referring to the interrupted status. It's a shame that it is informal - if there's somewhere a spec should be precise and unambiguous, well, it's everywhere, but it's the threading primitives above all.
The way the interrupted status mechanism works in general is if that a thread receives an interruption while it's not interruptible (because it's running), then the interruption is essentially made to wait until the thread is interrupted, at which point it swoops in an causes an InterruptedException. This is an example of that mechanism.
A thread can be interrupted at any point in time, but it won't have any effect until that thread specifically checks its interrupted state with Thread.currentThread().isInterrupted() or when it reaches, or is already blocked by a call to Thread.sleep(long), Object.wait(long) or other standard JDK methods which throw InterruptedException such as those in the java.nio package. The thread's interrupt status is reset when you catch an InterruptedException or when you explicitly call Thread.interrupted() (see the documentation for that elusive method).
This JavaSpecialists article should explain a bit more about how thread interrupts work and how to deal with them properly.
You can use the following class to test the behavior. In this case, the loop is not interrupted and the thread dies when it gets to the sleep.
public class TestInterrupt{
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(){
public void run(){
System.out.println("hello");
try {
for (int i = 0 ; i < 1000000; i++){
System.out.print(".");
}
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("interrupted");
e.printStackTrace();
}
}
};
t.start();
Thread.sleep(100);
System.out.println("about to interrupt.");
t.interrupt();
}
}
The docs of InterruptedException seems to suggest that it can be interrupted at other times
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/InterruptedException.html
Thrown when a thread is waiting, sleeping, or otherwise paused for a long time and another thread interrupts it using the interrupt method in class Thread
Also since it is a checked exception, it will only be thrown by methods that declare it. See
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#interrupt()