Proper lock/unlock usage for Java Reentrant locks - java

I have a homework assignment called "The H2O problem" where I'm supposed to implement a class called H2OBarrier which has 3 methods.
HReady, a method called when a hydrogen atom (thread) is ready
OReady, a method called when an oxygen atom (thread) is ready
makeWater, a method called when 2 hydrogen atoms and one oxygen atom are ready
I'm supposed to do this using Java Reentrant locks and Conditions.
This is my code so far, and I'm wondering if I'm properly using lock and unlock.
public class H2OBarrier {
int hCount;
int oCount;
Lock lock = new ReentrantLock();
Condition hWait = lock.newCondition();
Condition oWait = lock.newCondition();
public void HReady() {
lock.lock();
hCount++;
try {
hWait.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void OReady(){
lock.lock();
oCount++;
try {
while(hCount<2 && oCount<1){
oWait.await();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
makeWater();
}
}
public void makeWater(){
hCount--;
hWait.signal();
lock.unlock();
hCount--;
hWait.signal();
lock.unlock();
oCount--;
oWait.signal();
lock.unlock();
}
}
Should I be calling unlock() anywhere other than in my makeWater method? The whole flow of the program seems to make pretty logical sense to me, I'd just like to make sure what I'm doing looks correct overall.

Your code is producing a deadlock. Imagine 5 o atoms go through first, 5 go into o queue produced by await(). Now it doesn't matter if 2 h atoms go through, all the h atoms will automatically wait because of your code.

Related

Simple thread program to understand synchronized, wait and notify

I'm looking at other examples here and in other sites and I'm not understanding what I'm doing wrong. I'm trying to do a program that one thread sets the value of an object to the values 1 to 10, but I want to wait for it to change the value until other thread reads it, so I can print them and have a list from 1 to 10.
My readThread run method just loops from 1 to 10 calling the following method:
private synchronized int receive() {
try {
wait();
int value = this.mainThread.getValor();
notify();
return value;
} catch (InterruptedException e) {
e.printStackTrace();
}
return -1;
}
My writeThread run method just loops from 1 to 10 calling the following method:
private synchronized void send(int n) {
try {
this.mainThread.setValor(n);
notify();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The main method is the following:
public static void main(String[] args) {
MainThread mt = new MainThread();
ReadThread rt = new ReadThread(mt);
WriteThread wt = new WriteThread(mt);
wt.start();
rt.start();
}
The class MainThead has the property "valor" defined with its getter and setter
Thank you for your help
There are a couple of obvious problems.
It looks as if you are synchronising on the same lock (there isn't enough code to be 100% sure). Generally you should create an object specifically to use as a lock.
send may be executed before receive. In that case the first notify will do nothing, and both threads will stall in wait.
In theory, there is no guarantee that wait will not wakeup spontaneously. For this and other reasons, you really want the wait inside a while loop.

How to interrupt thread to do work and then sleep after doing work?

I want to have a thread which does some I/O work when it is interrupted by a main thread and then go back to sleep/wait until the interrupt is called back again.
So, I have come up with an implementation which seems to be not working. The code snippet is below.
Note - Here the flag is a public variable which can be accessed via the thread class which is in the main class
// in the main function this is how I am calling it
if(!flag) {
thread.interrupt()
}
//this is how my thread class is implemented
class IOworkthread extends Thread {
#Override
public void run() {
while(true) {
try {
flag = false;
Thread.sleep(1000);
} catch (InterruptedException e) {
flag = true;
try {
// doing my I/O work
} catch (Exception e1) {
// print the exception message
}
}
}
}
}
In the above snippet, the second try-catch block catches the InterruptedException. This means that both of the first and second try-catch block are catching the interrupt. But I had only called interrupt to happen during the first try-catch block.
Can you please help me with this?
EDIT
If you feel that there can be another solution for my objective, I will be happy to know about it :)
If it's important to respond fast to the flag you could try the following:
class IOworkthread extends Thread {//implements Runnable would be better here, but thats another story
#Override
public void run() {
while(true) {
try {
flag = false;
Thread.sleep(1000);
}
catch (InterruptedException e) {
flag = true;
}
//after the catch block the interrupted state of the thread should be reset and there should be no exceptions here
try {
// doing I/O work
}
catch (Exception e1) {
// print the exception message
// here of course other exceptions could appear but if there is no Thread.sleep() used here there should be no InterruptedException in this block
}
}
}
}
This should do different because in the catch block when the InterruptedException is caught, the interrupted flag of the thread is reset (at the end of the catch block).
It does sound like a producer/consumer construct. You seem to kind of have it the wrong way around, the IO should be driving the algorithm. Since you stay very abstract in what your code actually does, I'll need to stick to that.
So let's say your "distributed algorithm" works on data of type T; that means that it can be described as a Consumer<T> (the method name in this interface is accept(T value)). Since it can run concurrently, you want to create several instances of that; this is usually done using an ExecutorService. The Executors class provides a nice set of factory methods for creating one, let's use Executors.newFixedThreadPool(parallelism).
Your "IO" thread runs to create input for the algorithm, meaning it is a Supplier<T>. We can run it in an Executors.newSingleThreadExecutor().
We connect these two using a BlockingQueue<T>; this is a FIFO collection. The IO thread puts elements in, and the algorithm instances take out the next one that becomes available.
This makes the whole setup look something like this:
void run() {
int parallelism = 4; // or whatever
ExecutorService algorithmExecutor = Executors.newFixedThreadPool(parallelism);
ExecutorService ioExecutor = Executors.newSingleThreadExecutor();
// this queue will accept up to 4 elements
// this might need to be changed depending on performance of each
BlockingQueue<T> queue = new ArrayBlockingQueue<T>(parallelism);
ioExecutor.submit(new IoExecutor(queue));
// take element from queue
T nextElement = getNextElement(queue);
while (nextElement != null) {
algorithmExecutor.submit(() -> new AlgorithmInstance().accept(nextElement));
nextElement = getNextElement(queue);
if (nextElement == null) break;
}
// wait until algorithms have finished running and cleanup
algorithmExecutor.awaitTermination(Integer.MAX_VALUE, TimeUnit.YEARS);
algorithmExecutor.shutdown();
ioExecutor.shutdown(); // the io thread should have terminated by now already
}
T getNextElement(BlockingQueue<T> queue) {
int timeOut = 1; // adjust depending on your IO
T result = null;
while (true) {
try {
result = queue.poll(timeOut, TimeUnits.SECONDS);
} catch (TimeoutException e) {} // retry indefinetely, we will get a value eventually
}
return result;
}
Now this doesn't actually answer your question because you wanted to know how the IO thread can be notified when it can continue reading data.
This is achieved by the limit to the BlockingQueue<> which will not accept elements after this has been reached, meaning the IO thread can just keep reading and try to put in elements.
abstract class IoExecutor<T> {
private final BlockingQueue<T> queue;
public IoExecutor(BlockingQueue<T> q) { queue = q; }
public void run() {
while (hasMoreData()) {
T data = readData();
// this will block if the queue is full, so IO will pause
queue.put(data);
}
// put null into queue
queue.put(null);
}
protected boolean hasMoreData();
protected abstract T readData();
}
As a result during runtime you should at all time have 4 threads of the algorithm running, as well as (up to) 4 items in the queue waiting for one of the algorithm threads to finish and pick them up.

What is the proper method to release a Semaphore object in Java? [duplicate]

This question already has answers here:
Proper way to try-catch a semaphore
(3 answers)
Closed 5 years ago.
This is the code written in most of the resources online. But it is not correct because consider a scenario when a thread is blocking, and is then interrupted.
The thread will still release the lock even though it has not acquired the lock. This is incorrect. So what is the correct implementation of releasing a semaphore in java?
Semaphore lock = new Semaphore(1);
add(){
try {
lock.acquire();
// critical section
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}finally{
lock.release()
}
}
I think this is the correct solution:-. Is it?
try {
lock.acquire();
try {
// do some stuff here
} finally {
lock.release();
}
} catch(InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException(ie);
}
Semaphores have no concept of ownership. The permits aren't real things, it's just a count the semaphore keeps. So the question is, is the count right after the method executes?
If you're interrupted do you leave the method with one available permit or two?
The semaphore examples on Oracle's site in the api docs don't have any finally blocks, in a lot of cases they're not relevant.
If you're using this semaphore to implement a mutex and it has only one permit, I expect it should have a try-finally block just like using a lock (from the ReentrantLock api doc):
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
If the code eats the InterruptedException and lets the thread proceed on its way then whether the count is correct at the end of the method becomes important, it may keep other calls from acquiring the permit.
The general pattern I use whenever I get something, work with it, and release it is to get it above the try block, then work with it in the try block, and close/release/cleanup in the finally block. This goes for IO, JDBC resources, whatever. You can try to avoid this, put the acquisition in the try block, then
check for null before you clean it up. You can also try to do too much in your finally block, fail to catch exceptions on close, and create a resource leak. It's better to minimize the amount of code in the finally blocks.
A correct example is at http://jcip.net/listings/BoundedHashSet.java (from the book Java Concurrency
In Practice):
public boolean add(T o) throws InterruptedException {
sem.acquire();
boolean wasAdded = false;
try {
wasAdded = set.add(o);
return wasAdded;
} finally {
if (!wasAdded)
sem.release();
}
}
This shows a try block with a finally that does some cleanup (releasing a permit if it turned out nothing got added to the set), where acquire is called before that try-block is entered.
If in this example the acquire call was moved to within the try block, it wouldn't matter. I think putting the call above the try block is better style, but in this example it doesn't affect correctness, because it uses the flag to decide whether to release a permit.
I would use a flag like in the jcip example, set it to true after acquiring, and only release if the flag is set. That way you can put the acquire within the try block.
boolean wasAcquired = false;
try {
sem.acquire();
wasAcquired = true;
// crit sect
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
} finally {
if (wasAcquired)
sem.release();
}
Or consider acquireUninterruptibly(). But think about, if these calls don't throw the InterruptedException, what part of your code makes sure the code actually stops working when an interrupt request is received? It looks like you could fall into an unproductive cycle where threads try to acquire, throw InterruptedException, catch it and set the interrupt status, then do the same thing again the next time a thread tries to acquire, over and over and over. Throwing InterruptedException lets you respond quickly to a request for cancellation while making sure cleanup is done in finally blocks.
Just add a flag that indicates if the lock was acquired:
boolean acquired = false;
try {
lock.acquire();
acquired = true;
// critical section
} catch (InterruptedException e) {
// do anything
} finally {
if (acquired) {
lock.release()
}
}
Another solution is to use Semaphore.acquireUninterruptibly().
The thread will still release the lock even though it has not acquired the lock. This is incorrect.
No it isn't. There is nothing improper here. From the Javadoc:
There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire(). Correct usage of a semaphore is established by programming convention in the application.
There is no problem here to solve.

wait and notifyall waiting for other thread

I am doing the chef, bread, and customer scenario in Java with thread. So basically the chef makes a bread, the customer eats it, the chef makes more. The maximum is 20. The chef stop making bread when there are 20. The customer stop eating when there is none left. But everytime I use notifyall, it wait four seconds before the customer eat it(supposed to make 3 more breads).
Here is the code for run in the Chef class(implements runnable)
public void run(){
int id = 0;
while(true){
if(Basket.breadList.size() == 20){
synchronized(Basket.breadList){
try {
Basket.breadList.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Bread bread = new Bread(id);
System.out.println("Bread " + id + " had just been made. ");
synchronized(Basket.breadList){
Basket.breadList.notifyAll();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
id++;
}
}
}
Here is the code for Customer:
public void run(){
int id;
while(true){
if(Basket.breadList.size() == 0){
synchronized(Basket.breadList){
try {
Basket.breadList.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
id = Basket.breadList.get(Basket.breadList.size()-1).id;
Basket.breadList.remove(Basket.breadList.size()-1);
System.out.println("Bread " + id + " had just been eaten. ");
synchronized(Basket.breadList){
Basket.breadList.notifyAll();
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Here is the code in the controller:
public static void main(String[] args) {
Chef chef = new Chef();
Customer customer = new Customer();
Thread t1 = new Thread(chef);
Thread t2 = new Thread(customer);
t1.start();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t2.start();
}
Basket.breadList is just an arraylist of breads.
please help. Much appreciated!
After your Customer eats any bread whatsoever, it always waits 4 seconds. There is nothing to prevent this wait (typically some if () should be in place).
Rule: never sleep() unconditionally, unless you absolutely sure this is how it is supposed to be. You always sleep() because there is nothing else to accomplish and probably will not be for a while. So you need to check if there is.
Also, notifyAll() is typically done immediately after some prior action that makes things available for other threads to process.
Rule: call notifyAll() on a container immediately after you put something in it.
It is also not clear, in which code and at what time Chef adds the Bread to the basket. I assume bread adds itself in its own constructor - if so, it is an anti-pattern. Keep bread simple and healthy, it will taste better this way. Make Chef do the work. I would freak out if, while kneading and baking itself bread crawls into the basket.
Generally speaking, try to write your code exactly as actors in real world would act. Would Chef notify customer basket is not empty? When? Would customer notify Chef when basket is empty? When? When does either of them wait?
Your code is not locking effectively, so that while one thread is working the other can tamper with the data. Here's an example showing a better way for the backer to bake a loaf of bread, then wait while the bread supply is maxed out, then add the loaf to the inventory:
try {
while (true) {
Thread.sleep(4000);
Bread bread = new Bread(id++);
synchronized(Basket.breadList) {
while (Basket.breadList.size() == 20) {
Basket.breadList.wait();
}
Basket.breadList.add(bread);
Basket.breadList.notifyAll();
}
}
} catch (InterruptedException e) {
}
The wait method releases the lock, then re-acquires the lock before it can exit. Since this example holds the lock while it is checking and acting, once the inner while loop is exited from it is certain that the breadList contains less than 20 items. The customer should be rewritten similarly.
This version waits in a loop while holding the lock, checking the condition after emerging from the wait, because something may have changed while your thread didn't have the lock.
Also, just because your thread woke up doesn't mean you got a notification. The wait method can exit without having received a notification. See the Oracle tutorial for how to use wait and notify.
The only way for your thread to know what the size of the list really is is to check it while holding the lock, otherwise it could be changing on you (the other thread can be swapped in and change something in between your check and whatever action you take), resulting in the first thread basing its decisions on possibly stale information.
Likewise your customer shouldn't be removing something from the shared list without holding the lock on it. ArrayList is not threadsafe, also you don't want the state to change in between removing an item and sending the notification. If you are removing something from the list and then want to perform a notification, acquire the lock, then do the removal and notify together while holding the lock.
Don't hold a lock while sleeping, it's pointless and bad for performance. It would be better in this example, if you want to simulate needing time to create bread, for the sleep to come before the call to the Bread constructor.
The way your code swallows InterruptedException doesn't help your thread actually exit cleanly once interrupted. If you catch the InterruptedException outside the while (true) loop then the thread will respond to interruption by actually quitting its work and terminating.
The baker and customer should not be in charge of locking, it's confusing and makes it harder to understand how multithreading is applicable to real-life situations. Use a queue here, making the baker a producer and the customer a consumer. You have a shared data structure already, the arrayList, but you chose a data structure that isn't threadsafe and can't do blocking, the shared data structure needs to be in charge of protecting its own integrity. That way the roles are much clearer, with the locking, waiting, and notifying taking place in the shared data structure and not in the threads. Using a blocking queue from the java.util.concurrent package would be a good choice here, or write your own if you want the experience, it should be do-able once you read the linked tutorial. Once you use a separate queue the run method for the baker becomes:
public void run() {
try {
int id = 0;
while (true) {
Thread.sleep(4000);
queue.put(new Bread(id++));
}
} catch (InterruptedException e) {
}
}
while the queue's put method would be
public synchronized void put(Bread b) throws InterruptedException {
while (breadList.size() == 20) {
wait();
}
breadList.add(b);
notifyAll();
}
assuming that breadList is a private instance member of the Queue.

Code in synchronized block

Is there any difference of placing timlesProc(100); inside or outside synchronized block like shown commented line in ThreadA.
According to my understanding there is no difference, because both threads are in running mode and both can be executed in the same time. But according experiments, when timlesProc(100); is inside synchronized - it always runs first, then b.sync.wait(); and no 'wait forever' problem. When timlesProc(100); outside synchronized - I always get 'waiting forever'. Why it is so, or my understanding is not correct?
class ThreadA {
public static void timlesProc(int count)
{
for(int i=0;i<count;i++)
{
System.out.println(Thread.currentThread().getName()+" "+ Integer.toString(i));
}
}
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
//timlesProc(100);
synchronized(b.sync)
{
timlesProc(100);
try
{
System.out.println("Waiting for b to complete...");
b.sync.wait();
System.out.println("waiting done");
} catch (InterruptedException e) {}
}
}
}
class ThreadB extends Thread {
Integer sync = new Integer(1);
public void run() {
synchronized(sync)
{
sync.notify();
System.out.println("notify done");
}
}
}
You have a race condition. If the timlesProc method is outside the synchronized, it's very probable that you will have a context switch and the other Thread will be able to execute acquiring the lock and notifying the main Thread (even if it wasn't waiting). Then when you get to
b.sync.wait();
you wait forever because there is nothing left to notify() it.
If you put the timlesProc inside the synchronized, you reach the wait() and then get notified. The program then finishes.
See Cruncher's answer for another possibility of your program waiting forever.
Actually, even if the timlesProc call is inside the synchronized block, there is still a race condition, just less likely to happen.
If b.start() happens, and it aquires the sync lock before the main thread, then it will still notify first causing the same problem that Sotirios Delimanolis mentions in his answer.

Categories

Resources