Correct implementation of lock for semaphore? [duplicate] - java

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.

Related

Why does BoundedExecutor have to catch RejectedExecutionException?

As to BoundedExecutor in the book Java Concurrency in Practice, task submission has been throttled by semaphore. When would the underlying executor throw a RejectedExecutionException? Maybe when operating system runs out of threads?
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command) throws InterruptedException, RejectedExecutionException
{
semaphore.acquire();
try {
exec.execute(new Runnable() {
#Override public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
throw e;
}
}
}
Part of the contract of Executor.execute() is that it can throw a RejectedExecutionException:
if this task cannot be accepted for execution
What that means for any given Executor implementation is up to the discretion of that implementation. I could create an OnlyOnSundaysExecutor that rejects tasks unless the current day of the week is Sunday. You would have to check the documentation for the various Executor implementations to see under what circumstances they would throw a RejectedExecutionException exception.
Regardless of the circumstances under which an exception might be thrown, it is important to keep your application in a consistent state, even when exceptions occur.
Here, the semaphore that has been acquired should always get released. For most resources that should get released under all circumstances, you would use a try {} finally { /* release action */ } construct to ensure the release even in the exceptional case, but here, we have the special situation that the release action should be performed only in the exceptional case, as in the successful case, the submitted Runnable will perform the release action (note that within the Runnable, finally is indeed being used).
So the code is supposed to handle the case when a RejectedExecutionException is thrown. We might want to do that for every RuntimeException or Error, but the problem is, RejectedExecutionException is the only exception type where we know for sure that the runnable will never get executed. For all other kinds of exceptions, it is possible that it will still run.
To make the cleanup safe, you would need another atomic toggle:
public void submitTask(final Runnable command) throws InterruptedException {
AtomicBoolean proceed = new AtomicBoolean(true);
semaphore.acquire();
try {
exec.execute(new Runnable() {
#Override public void run() {
if(proceed.compareAndSet(true, false)) try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch(Throwable e) {
if(proceed.compareAndSet(true, false)) semaphore.release();
throw e;
}
}
Now, in every exceptional case, an attempt to release the semaphore will be made, unless the Runnable flagged that it is already running. Or the Runnable will not proceed if it detects that the semaphore has been released due to an exception in the submitting code.
This is, of course, more complicated than the book example and possibly distracting from the original intent of the example. Also, it uses the Java 7 feature of being able to easily catch and re-throw all possible exceptions of the try block. This wasn’t available when the book was written.

Should I Thread.currentThread.interrupt() before I throw an exception back?

I am implementing an interface which throws IOException. In my implementation, I call another method which can block, and therefore throw InterruptedException.
Context:
I want to end the treatment if I am interrupted;
this is not a thread I created myself.
My current idea is to do as such (skeleton code):
#Override
public void implementedMethod()
throws IOException
{
try {
methodThatBlocks();
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
throw new IOException();
}
}
is that the correct way? Or should I just throw and not .interrupt()?
Yes, you should call interrupt() to let the calling code know that the thread has been interrupted. If you don't do it, since the InterruptedException clears it, the calling code will have no way to know about the interruption and won't stop running although it should.
Let me quote Java Concurrency in Practice:
Restore the interrupt. Sometimes you cannot throw InterruptedException, for instance when your code is part of a Runnable. In these situations, you must catch InterruptedException and restore the interrupted status by calling interrupt on the current thread, so that code higher up the call stack can see that an interrupt was issued,
as demonstrated in Listing 5.10.
public class TaskRunnable implements Runnable {
BlockingQueue<Task> queue;
...
public void run() {
try {
processTask(queue.take());
} catch (InterruptedException e) {
// restore interrupted status
Thread.currentThread().interrupt();
}
}
}
Of course not. The thread is already unblocked and running. In the code that is about to throw an exception. What would be the point?

Need to semaphore.relase() if semaphore.acquire() gets InterruptedException?

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();
}

Is synchronized keyword exception-safe? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Side effects of throwing an exception inside a synchronized clause?
I am wondering if synchronized is exception-safe? Say, an uncaught exception happens within the synchronized block, will the lock be released?
When in doubt, check the Java Language Specification. In section 17.1 you'll find:
If execution of the method's body is ever completed, either normally
or abruptly, an unlock action is automatically performed on that same
monitor.
Synchronize is neither thread-safe nor non-thread-safe. The way you phrased the question just doesn't make sense.
In case of an exception the lock will be released.
Only a System.exit prevents a block exiting normally. It means finally blocks are not called and locks are not released.
private static final Object lock = new Object();
public static void main(String... args) throws ParseException {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Locking");
synchronized (lock) {
System.out.println("Locked");
}
}
}));
synchronized (lock) {
System.exit(0);
}
}
prints
Locking
and hangs. :|
Yes, it will. The major point of the synchronize keyword is to make multi-threaded coding easier.
Yes the object will become unlocked if an exception is thrown and not caught.
You can find some code examples here.
Yes it will.
As a side note, the try-finally construct will ensure the finally block will be executed when the try exits
try {
someFunctionThatMayThrow();
} finally {
willAlwaysBeExecuted();
}

Is there a Mutex in Java?

Is there a Mutex object in java or a way to create one?
I am asking because a Semaphore object initialized with 1 permit does not help me.
Think of this case:
try {
semaphore.acquire();
//do stuff
semaphore.release();
} catch (Exception e) {
semaphore.release();
}
if an exception happens at the first acquire, the release in the catch block will increase the permits, and the semaphore is no longer a binary semaphore.
Will the correct way be?
try {
semaphore.acquire();
//do stuff
} catch (Exception e) {
//exception stuff
} finally {
semaphore.release();
}
Will the above code ensure that the semaphore will be binary?
Any object in Java can be used as a lock using a synchronized block. This will also automatically take care of releasing the lock when an exception occurs.
Object someObject = ...;
synchronized (someObject) {
...
}
You can read more about this here: Intrinsic Locks and Synchronization
See this page: http://www.oracle.com/technetwork/articles/javase/index-140767.html
It has a slightly different pattern which is (I think) what you are looking for:
try {
mutex.acquire();
try {
// do something
} finally {
mutex.release();
}
} catch(InterruptedException ie) {
// ...
}
In this usage, you're only calling release() after a successful acquire()
No one has clearly mentioned this, but this kind of pattern is usually not suited for semaphores. The reason is that any thread can release a semaphore, but you usually only want the owner thread that originally locked to be able to unlock. For this use case, in Java, we usually use ReentrantLocks, which can be created like this:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
private final Lock lock = new ReentrantLock(true);
And the usual design pattern of usage is:
lock.lock();
try {
// do something
} catch (Exception e) {
// handle the exception
} finally {
lock.unlock();
}
Here is an example in the java source code where you can see this pattern in action.
Reentrant locks have the added benefit of supporting fairness.
Use semaphores only if you need non-ownership-release semantics.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
private final Lock _mutex = new ReentrantLock(true);
_mutex.lock();
// your protected code here
_mutex.unlock();
I think you should try with :
While Semaphore initialization :
Semaphore semaphore = new Semaphore(1, true);
And in your Runnable Implementation
try
{
semaphore.acquire(1);
// do stuff
}
catch (Exception e)
{
// Logging
}
finally
{
semaphore.release(1);
}
Mistake in original post is acquire() call set inside the try loop.
Here is a correct approach to use "binary" semaphore (Mutex):
semaphore.acquire();
try {
//do stuff
} catch (Exception e) {
//exception stuff
} finally {
semaphore.release();
}
Each object's lock is little different from Mutex/Semaphore design.
For example there is no way to correctly implement traversing linked nodes with releasing previous node's lock and capturing next one. But with mutex it is easy to implement:
Node p = getHead();
if (p == null || x == null) return false;
p.lock.acquire(); // Prime loop by acquiring first lock.
// If above acquire fails due to interrupt, the method will
// throw InterruptedException now, so there is no need for
// further cleanup.
for (;;) {
Node nextp = null;
boolean found;
try {
found = x.equals(p.item);
if (!found) {
nextp = p.next;
if (nextp != null) {
try { // Acquire next lock
// while still holding current
nextp.lock.acquire();
}
catch (InterruptedException ie) {
throw ie; // Note that finally clause will
// execute before the throw
}
}
}
}finally { // release old lock regardless of outcome
p.lock.release();
}
Currently, there is no such class in java.util.concurrent, but you can find Mutext implementation here Mutex.java. As for standard libraries, Semaphore provides all this functionality and much more.
To ensure that a Semaphore is binary you just need to make sure you pass in the number of permits as 1 when creating the semaphore. The Javadocs have a bit more explanation.

Categories