First, we'll discuss the synchronized keyword, which is the simplest way to implement a mutex in Java. Every object in Java has an intrinsic lock associated with it. The synchronized method and the synchronized block use this intrinsic lock to restrict the access of the critical section to only one thread at a time.
Semaphores – Restrict the number of threads that can access a resource. Example, limit max 10 connections to access a file simultaneously. Mutex – Only one thread to access a resource at once. Example, when a client is accessing a file, no one else should have access the same file at the same time.
A Semaphore in Java controls access to a shared resource through a counter. It is a thread synchronization construct used to send signals between threads to avoid missed signals or guard a critical section.
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()
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();
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With