Not able to understand or implement Semaphore - java

I have written below class to understand SemaPhore. However the result is unexpected. I couldn't understand actual work of SemaPhore. How it is used as a lock, signaling and for counting?
public class TrySemaPhore
{
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
Semaphore semaphore = new Semaphore(2);
Runnable newTask= () -> {
boolean permit = false;
try {
permit = semaphore.tryAcquire();
if(permit)
System.out.println("doing work");
} finally {
if(permit){
semaphore.release();
System.out.println("Work done!!");
}
}
};
for(int i=0; i<=4; i++){
executor.submit(newTask);
}
stop(executor);
}
private static void stop(ExecutorService executor) {
/*code to stop executor*/
}
}
Result
doing work
Work done!!
doing work
Work done!!
doing work
Work done!!
doing work
Work done!!
doing work
Work done!!
I have 10 Fixed number of Threads. I have 5 different tasks(for loop) which needs to complete. I have Semaphore with 2 permits. I want to understand Semaphore and it's benefit in a very simple way (not like theory available through googling).

A counting semaphore. Conceptually, a semaphore maintains a set of
permits. Each acquire blocks if necessary until a permit is
available, and then takes it. Each release adds a permit,
potentially releasing a blocking acquirer.
Before obtaining an item each thread must acquire a permit from
the semaphore, guaranteeing that an item is available for use. When
the thread has finished with the item it is returned back to the
pool and a permit is returned to the semaphore, allowing another
thread to acquire that item. Note that no synchronization lock is
held when acquire is called as that would prevent an item
from being returned to the pool. The semaphore encapsulates the
synchronization needed to restrict access to the pool, separately
from any synchronization needed to maintain the consistency of the
pool itself.
Use case:
1.An unbounded queue requires one semaphore, (to count the queue entries), and a mutex-protected thread-safe queue, (or equivalent lock-free thread-safe queue). The semaphore is intialized to zero. Producers lock the mutex, push an object onto the queue, unlock the mutex and signal the semaphore. Consumers wait on the semaphore, lock the mutex, pop the object and unlock the mutex.
2.Object pool where you can restrict the number of resource using semaphore .Multiple thread try to acquire the object in the pool and you have limited number of object then some thread will wait until some thread releases.
class Pool {
private static final int MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
if (markAsUnused(x))
available.release();
}

Related

non-fair ReentrantReadWriteLock write and read lock priorities [duplicate]

ReentrantReadWriteLock has a fair and non-fair(default) mode, but the document is so hard for me to understand it.
How can I understand it? It's great if there is some code example to demo it.
UPDATE
If I have a writing thread, and many many reading thread, which mode is better to use? If I use non-fair mode, is it possible the writing thread has little chance to get the lock?
Non-fair means that when the lock is ready to be obtained by a new thread, the lock gives no guarantees to the fairness of who obtains the lock (assuming there are multiple threads requesting the lock at the time). In other words, it is conceivable that one thread might be continuously starved because other threads always manage to arbitrarily get the lock instead of it.
Fair mode acts more like first-come-first-served, where threads are guaranteed some level of fairness that they will obtain the lock in a fair manner (e.g. before a thread that started waiting long after).
Edit
Here is an example program that demonstrates the fairness of locks (in that write lock requests for a fair lock are first come, first served). Compare the results when FAIR = true (the threads are always served in order) versus FAIR = false (the threads are sometimes served out of order).
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class FairLocking {
public static final boolean FAIR = true;
private static final int NUM_THREADS = 3;
private static volatile int expectedIndex = 0;
public static void main(String[] args) throws InterruptedException {
ReentrantReadWriteLock.WriteLock lock = new ReentrantReadWriteLock(FAIR).writeLock();
// we grab the lock to start to make sure the threads don't start until we're ready
lock.lock();
for (int i = 0; i < NUM_THREADS; i++) {
new Thread(new ExampleRunnable(i, lock)).start();
// a cheap way to make sure that runnable 0 requests the first lock
// before runnable 1
Thread.sleep(10);
}
// let the threads go
lock.unlock();
}
private static class ExampleRunnable implements Runnable {
private final int index;
private final ReentrantReadWriteLock.WriteLock writeLock;
public ExampleRunnable(int index, ReentrantReadWriteLock.WriteLock writeLock) {
this.index = index;
this.writeLock = writeLock;
}
public void run() {
while(true) {
writeLock.lock();
try {
// this sleep is a cheap way to make sure the previous thread loops
// around before another thread grabs the lock, does its work,
// loops around and requests the lock again ahead of it.
Thread.sleep(10);
} catch (InterruptedException e) {
//ignored
}
if (index != expectedIndex) {
System.out.printf("Unexpected thread obtained lock! " +
"Expected: %d Actual: %d%n", expectedIndex, index);
System.exit(0);
}
expectedIndex = (expectedIndex+1) % NUM_THREADS;
writeLock.unlock();
}
}
}
}
Edit (again)
Regarding your update, with non-fair locking it's not that there's a possibility that a thread will have a low chance of getting a lock, but rather that there's a low chance that a thread will have to wait a bit.
Now, typically as the starvation period increases, the probability of that length of time actually occuring decreases...just as flipping a coin "heads" 10 consecutive times is less likely to occur than flipping a coin "heads" 9 consecutive times.
But if the selection algorithm for multiple waiting threads was something non-randomized, like "the thread with the alphabetically-first name always gets the lock" then you might have a real problem because the probability does not necessarily decrease as the thread gets more and more starved...if a coin is weighted to "heads" 10 consecutive heads is essentially as likely as 9 consecutive heads.
I believe that in implementations of non-fair locking a somewhat "fair" coin is used. So the question really becomes fairness (and thus, latency) vs throughput. Using non-fair locking typically results in better throughput but at the expense of the occasional spike in latency for a lock request. Which is better for you depends on your own requirements.
When some threads waiting for a lock, and the lock has to select one thread to get the access to the critical section:
In non-fair mode, it selects thread without any criteria.
In fair mode, it selects thread that has waiting for the most time.
Note: Take into account that the behavior explained previously is only used with the lock() and unlock() methods. As the tryLock() method doesn't put the thread to sleep if the Lock interface is used, the fair attribute doesn't affect its functionality.

Is this synchronized block need?

Is the synchronized block on System.out.println(number); need the following code?
import java.util.concurrent.CountDownLatch;
public class Main {
private static final Object LOCK = new Object();
private static long number = 0L;
public static void main(String[] args) throws InterruptedException {
CountDownLatch doneSignal = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Worker worker = new Worker(doneSignal);
worker.start();
}
doneSignal.await();
synchronized (LOCK) { // Is this synchronized block need?
System.out.println(number);
}
}
private static class Worker extends Thread {
private final CountDownLatch doneSignal;
private Worker(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
}
#Override
public void run() {
synchronized (LOCK) {
number += 1;
}
doneSignal.countDown();
}
}
}
I think it's need because there is a possibility to read the cached value.
But some person say that:
It's unnecessary.
Because when the main thread reads the variable number, all of worker thread has done the write operation in memory of variable number.
doneSignal.await() is a blocking call, so your main() will only proceed when all your Worker threads have called doneSignal.countDown(), making it reach 0, which is what makes the await() method return.
There is no point adding that synchronized block before the System.out.println(), all your threads are already done at that point.
Consider using an AtomicInteger for number instead of synchronizing against a lock to call += 1.
It is not necessary:
CountDownLatch doneSignal = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Worker worker = new Worker(doneSignal);
worker.start();
}
doneSignal.await();
// here the only thread running is the main thread
Just before dying each thread countDown the countDownLatch
#Override
public void run() {
synchronized (LOCK) {
number += 1;
}
doneSignal.countDown();
}
Only when the 10 thread finish their job the doneSignal.await(); line will be surpass.
It is not necessary because you are waiting for "done" signal. That flush memory in a way that all values from the waited thread become visible to main thread.
However you can test that easily, make inside the run method a computation that takes several (millions) steps and don't get optimized by the compiler, if you see a value different than from the final value that you expect then your final value was not already visible to main thread. Of course here the critical part is to make sure the computation doesn't get optimized so a simple "increment" is likely to get optimized. This in general is usefull to test concurrency where you are not sure if you have correct memory barriers so it may turn usefull to you later.
synchronized is not needed around System.out.println(number);, but not because the PrintWriter.println() implementations are internally synchronized or because by the time doneSignal.await() unblocks all the worker threads have finished.
synchronized is not needed because there's a happens-before edge between everything before each call to doneSignal.countDown and the completion of doneSignal.await(). This guarantees that you'll successfully see the correct value of number.
Needed
No.
However, as there is no (documented) guarantee that there will not be any interleaving it is possible to find log entries interleaved.
System.out.println("ABC");
System.out.println("123");
could print:
AB1
23C
Worthwhile
Almost certainly not. Most JVMs will implement println with a lock open JDK does.
Edge case
As suggested by #DimitarDimitrov, there is one further possible use for that lock and it is to ensure a memory barrier is crossed befor accessing number. If that is the concern then you do not need to lock, all you need to do is make number volatile.
private static volatile long number = 0L;

Is it possible that 2 synchronized methods of an object are accessible by 2 threads at the same time?

This question was asked to me in an interview. Before I had told him this,
Once a thread enters any synchronized method on an instance, no other
thread can enter any other synchronized method on the same instance.
Consider the snippet:
Q1:
public class Q1 {
int n;
boolean valueSet = false;
synchronized int get() {
while (!valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
while (valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
Producer1:
public class Producer1 implements Runnable {
Q1 q;
Producer1(Q1 q) {
this.q = q;
new Thread(this, "Producer").start();
}
#Override
public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}
Consumer1
public class Consumer1 implements Runnable {
Q1 q;
Consumer1(Q1 q) {
this.q = q;
new Thread(this, "Consumer").start();
}
#Override
public void run() {
while (true) {
q.get();
}
}
}
PC1:
public class PC1 {
public static void main(String args[]) {
Q1 q = new Q1();
new Producer1(q);
new Consumer1(q);
System.out.println("Press Control-C to stop.");
}
}
So, he asked as soon as you have created this thread new Producer1(q), then according to you, the synchronized int get() method must have been locked by the same thread, i.e, by new Producer1(q) when it accessed synchronized int put(). I said yes.
But I checked in eclipse, get is callable by new Consumer1(q). The program works perfect.
Where am I going wrong?
O/P:
The call to wait() will release the monitor for the time waiting.
That's what is documented for Object.wait():
The current thread must own this object's monitor. The thread
releases ownership of this monitor and waits until another thread
notifies threads waiting on this object's monitor to wake up
either through a call to the notify method or the
notifyAll method. The thread then waits until it can
re-obtain ownership of the monitor and resumes execution.
Once a thread enters any synchronized method on an instance, no other
thread can enter any other synchronized method on the same instance.
What you forgot to add here is "except if the lock is released".
...and it is the case in your example, when calling wait.
The documentation specify :
The thread releases ownership of this monitor and waits until another
thread notifies threads waiting on this object's monitor to wake up
either through a call to the notify method or the notifyAll method.
Since the lock is released, you step in the other method (and the condition is true because the boolean was modified). Once in the other method, you release the lock again, then call notify and you wake up the old thread which terminates (re-modify boolean to pass the condition in other method, and notify). That way you step between both methods ad-infinitum.
wait() and notify() is acts as a signal between threads, to control the threads to do or to not do the stuff.
The program works perfect because here 2 threads (Producer, Consumer) which fight for the one lock (monitor). When Consumer aquires the lock (Q1 object) then Producer is waiting for the lock. When Consumer finishes his work it release the lock. Consumer releases the lock also when wait() method has been called, because wait() sets thread to Waiting state with lock release. It's time for Producer to aquire the lock and does his work. When Producer thread notify() calls then Consumer continue his work (when aquired the lock). The same is right for Producer.
Resume: Q1 object is a lock for all threads. If it aquired someone then others are blocked and the answer is - it not possible to get an access at the same time to the get(), put() methods more then 2 threads.
I think that the question is ambiguous. (E.g., what does "accessible" mean?)
IMO, a good interview question should not have a right answer and a wrong answer. A good interview question should be a conversation starter, that gives you an opportunity to show how much you know about the subject.
When I am asking the interview questions, I like a candidate who can see through the question, and get down to the underlying mechanism. E.g.,
What the JLS guarantees is that no two threads can be _synchronized_
on the same instance at the same time...
Then we could explore questions like, how could two threads enter the same synchronized method at the same time? (e.g., synchronized on different instances), how could two threads be in the same synchronized method for the same instance at the same time (one of them could be in a wait() call), ...
A thread can not access a synchronized block of code unless it has aquired a lock on the object that guards the block. In your case, the synchronized keyword uses the lock of the object in which it has been declared. So as long as a thread is executing get(), no other thread can execute the put().
If you apply this, when put() sets the value, it notifies consumer which accepts the value. The code should work even after you have removed the wait() and notify() calls from both get and put methods

Deadlock caused by blocking methods

Say we create a thread which runs a synchronized method. This method tries to take() from an empty blocking queue. Now let a separate thread then try to put() and element onto the blocking queue while synchronized on the same object.
This causes a deadlock:
The first thread will not release the lock until an element is added to the queue.
The second thread cannot add an element until the lock is free for it to acquire.
If the two actions need to be atomic and run on separate threads, how can this be achieved without causing a deadlock?
I understand that take() and put() are thread-safe. My question is for when they are used as part of larger actions that must be atomic.
Example:
import java.util.concurrent.*;
public class DeadlockTest {
String input = "Nothing added yet!";
LinkedBlockingQueue<String> buffer = new LinkedBlockingQueue<>();
public synchronized String getFromBuffer() {
System.out.println("Trying to get input from buffer.");
try {
input = buffer.take();
} catch (InterruptedException ex) {}
System.out.println("Got:" + input + "\n");
return input;
}
public static void main(String[] args) throws InterruptedException {
DeadlockTest dl = new DeadlockTest();
new Thread(() -> {
dl.getFromBuffer();
}).start();
// Give new thread time to run.
Thread.sleep(500);
synchronized (dl) {
String message = "Hello, world!";
System.out.println("Adding: " + message);
dl.buffer.put(message);
System.out.println("Added!\n");
System.out.println("Message: " + dl.input);
}
}
}
Say we create a thread which runs a synchronized method. This method tries to take() from an empty blocking queue.
Sounds like bad design. It's usually a mistake to call any blocking methods from within a synchronized method or a synchronized statement.
If the two actions need to be atomic and run on separate threads, how can this be achieved without causing a deadlock?
Well, there's two possibilities:
In one case, the two threads are acting on different data. In that case, they should be using different locks, and they won't interfere with one another at all.
In the other case, the two threads are acting on the same data. In that case, they should lock the same lock, and one thread will have to wait for the other.
Maybe you misunderstand how a blocking queue works. If one thread is waiting to take() something from a blocking queue, that should never prevent another thread from calling put(). That would be the exact opposite of what you want.
What you want (and what you'll get from any of the blocking queue implementations in the Java standard library) is that the put() operation in the second thread will wake up the thread that's waiting to take() something from the queue.

A thread holding multiple lock goes into wait() state. Does it release all holding locks?

I wrote this program to check if a thread t1 holding lock on two different objects :
Lock.class and MyThread.class goes into waiting mode on MyThread.class instance using MyThread.class.wait().It does not release lock on Lock.class instance. why so ? I have been thinking that once a thread goes into wait mode or it dies it releases all the acquired locks.
public class Lock {
protected static volatile boolean STOP = true;
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread);
t1.start();
while(STOP){
}
System.out.println("After while loop");
/*
*
*/
Thread.sleep(1000*60*2);
/*
* Main thread should be Blocked.
*/
System.out.println("now calling Check()-> perhaps i would be blocked. t1 is holding lock on class instance.");
check();
}
public static synchronized void check(){
System.out.println("inside Lock.check()");
String threadName = Thread.currentThread().getName();
System.out.println("inside Lock.Check() method : CurrrentThreadName : "+ threadName);
}
}
class MyThread implements Runnable{
public MyThread() {
}
#Override
public void run() {
try {
System.out.println("inside Mythread's run()");
classLocking();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static synchronized void classLocking() throws InterruptedException{
System.out.println("inside Mythread.classLocking()");
String threadName = Thread.currentThread().getName();
System.out.println("inside MyThread.classLocking() : CurrrentThreadName : "+ threadName);
/*
* outer class locking
*/
synchronized (Lock.class) {
System.out.println("I got lock on Lock.class definition");
Lock.STOP = false;
/*
* Outer class lock is not released. Lock on MyThread.class instance is released.
*/
MyThread.class.wait();
}
}
}
You are correct that it doesn't release the other lock. As for why, it's because it isn't safe to do so. If it was safe to release the outer lock during the call to the inner function, why would the inner function be called with the other lock held at all?
Having a function release a lock it didn't acquire behind the programmer's back would destroy the logic of synchronized functions.
Yes it is working correctly. A thread goes into waiting status releases the corresponding lock instead of all locks. Otherwise think about that: if things are like what you thought, then when a thread waits it loses all the acquired locks, which makes advanced sequential execution impossible.
The semantics of wait() is that the Thread invoking it notices that a lock was already acquired by another thread, gets suspended and waits to be notified by the thread holding the lock when the latter one releases it (and invokes notify). It doesn't mean that while waiting it releases all the locks acquired. You can see the wait's invocations as a number of barriers the thread meets on the way to acquiring all the locks it needs to accomplish an action.
Regarding the question "Why a thread doesn't release all the locks acquired when invoking wait" , I think the answer is that, doing so would make it more prone to starvation and it would also slow down the progress in a multithreaded application (All threads would give up all their locks when invoking the first wait and would have to start over when they acquire the lock they are currently waiting for. So, they would be in a permanent battle for locks.
Actually, in such a system, the only thread able to finish execution would be the one which manages to find all locks free when it needs them. This is unlikely to happen)
From JavaDoc of method wait()
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

Categories

Resources