java.lang.IllegalMonitorStateException being thrown from methods running in threads - java

I am trying to create basic producer/consuner class using:
public class ProducerConsumer {
private final static int MAX_SIZE = 100;
private Queue<String> data = new PriorityQueue<>();
private Lock lock = new ReentrantLock();
private Condition bufferFull = lock.newCondition();
private Condition bufferEmpty = lock.newCondition();
public void produce(){
while(true) {
try {
lock.lock();
while (data.size() >= MAX_SIZE) {
bufferFull.await();
}
addData();
bufferEmpty.notifyAll();
} catch (InterruptedException e) {
System.out.println("error produce");
} finally {
lock.unlock();
}
}
}
public void consume(){
while(true) {
try {
lock.lock();
while (data.isEmpty()) {
bufferEmpty.await();
}
String value = data.poll();
System.out.println("Thread " + Thread.currentThread().getName() + " processing value " + value);
bufferFull.notifyAll();
} catch (InterruptedException e) {
System.out.println("error consume");
} finally {
lock.unlock();
}
}
}
private void addData(){
IntStream.range(0,10).forEach( i ->
data.add(new Date().toString())
);
}
public void start(int consumerNumber){
IntStream.range(0,consumerNumber)
.mapToObj(i -> new Thread(this::consume))
.collect(Collectors.toList())
.forEach(Thread::start);
Thread t = new Thread(this::produce);
t.start();
}
}
However it keeps throwing error: java.lang.IllegalMonitorStateException. My question is, why does it throw this error? method of this intance are running in threads, so they should own condition lock thus i dont understand meaning behind this error.
Thanks for help!

bufferEmpty.notifyAll() is the wrong method to call. That method requires you hold the monitor on the "bufferEmpty" object itself, which is unrelated to the lock instance you're using.
The right method to call is
bufferEmpty.signalAll();

Related

why does deadlock not happen

Deadlock describes a situation where two more threads are blocked because of waiting for each other forever. When deadlock occurs, the program hangs forever and the only thing you can do is to kill the program.
why deadlock does not happen in example producer consumer problem given below:
I wonder why call wait method in synchronized block does not causing deadlock when synchronized object is waiting for release of lock from other thread ?
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class WaitAndNotify {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
var th1 = new Thread(new Producer(list));
var th2 = new Thread(new Consumer(list));
th1.start();
th2.start();
}
}
class Producer implements Runnable {
private List<Integer> list;
private final Integer MAX_SIZE_LIST = 5;
public Producer(List<Integer> list) {
this.list = list;
}
#Override
public void run() {
Random rand = new Random();
for (;;) {
synchronized (this.list) {
if (list.size() == MAX_SIZE_LIST) { // check list is full or not
try {
System.out.println("list full wait producer");
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
var randNumber = rand.nextInt();
System.out.println("produce number => " + randNumber);
list.add(randNumber);
list.notify();
}
}
}
}
class Consumer implements Runnable {
private List<Integer> list;
public Consumer(List<Integer> list) {
this.list = list;
}
#Override
public void run() {
for (;;) {
synchronized (this.list) {
if (list.size() == 0) {
try {
System.out.println("list empty consumer wait");
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("consume number <= " + list.remove(0));
list.notify();
}
}
}
}
You probably think, that Consumer will block at list.wait() and Producer will block at synchronized (this.list).
It works, because list.wait() releases the ownership of list inside a synchronized block. After wait returns, the thread acquires the ownership again.
See Object.wait()
As we have already discussed here Deadlock did not happen because of the use of synchronized block, list.wait() and list.notify() methods.
Here is a nice example of deadlock : https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

Lock and Condition about thread communication in java

I'm a java beginner and I write below code while learning Thread in java. I think, if I lock in Resource.set() and comment out the Lock.unlock(), the code in Resource.out() can't be executed because I can't unlock in when I want to execute out method. BTW, whether I comment out the unlock in the set() or in out(), the program will execute in this way:
Thread[Thread-1,5,main]....Produce....chicken1
Thread[Thread-2,5,main]....Consume..........chicken1
Thread[Thread-0,5,main]....Produce....chicken2
Thread[Thread-3,5,main]....Consume..........chicken2 ......
I think a long time and don't understand about it. I just learned it, maybe I have a wrong understanding,so I hope someone's help.
Please forgive my poor English. Thank you very much. My code is here:
package Thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadStudying {
public static void main(String[] args) {
Resource r = new Resource();
Thread t0 = new Thread(new Producer(r));
Thread t1 = new Thread(new Producer(r));
Thread t2 = new Thread(new Consumer(r));
Thread t3 = new Thread(new Consumer(r));
t0.start();
t1.start();
t2.start();
t3.start();
}
static class Resource {
private String name;
private int count = 1;
boolean isOut = false;
Lock lock = new ReentrantLock();
Condition pro_con = lock.newCondition();
Condition consu_con = lock.newCondition();
public void set(String name) {
lock.lock();
try {
while (isOut) {
try {
pro_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name + count;
System.out.println(Thread.currentThread() + "....Produce...." + this.name);
count++;
isOut = true;
consu_con.signal();
}
finally {
lock.unlock();
}
}
public void out() {
lock.lock();
try {
while (!isOut) {
try {
consu_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread() + "....Consume.........." + this.name);
isOut = false;
pro_con.signal();
}
finally {
//lock.unlock();
}
}
}
static class Producer implements Runnable {
Resource r;
Producer(Resource r) {
this.r = r;
}
public void run() {
while (true) {
r.set("chicken");
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable {
Resource r;
Consumer(Resource r) {
this.r = r;
}
#Override
public void run() {
while (true) {
r.out();
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
In both producer and consumer, you are calling lock.await repeatly by
while (true) {
//
}
From the doc, when you call lock.await :
The lock associated with this Condition is atomically released
So, whether you comment out lock.unlock or not, both producer and consumer will not be blocked.
P.S. Use below code to log more details about getting and releasing lock:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadStudying {
public static void main(String[] args) {
Resource r = new Resource();
Thread t0 = new Thread(new Producer(r), "Producer 1");
Thread t1 = new Thread(new Producer(r), "Producer 2");
Thread t2 = new Thread(new Consumer(r), "Consumer 1");
Thread t3 = new Thread(new Consumer(r), "Consumer 2");
t0.start();
t1.start();
t2.start();
t3.start();
}
static class Resource {
private String name;
private int count = 1;
boolean isOut = false;
Lock lock = new ReentrantLock();
Condition pro_con = lock.newCondition();
Condition consu_con = lock.newCondition();
public void set(String name) {
System.out.println(Thread.currentThread() + "before lock");
lock.lock();
System.out.println(Thread.currentThread() + "get lock");
try {
while (isOut) {
try {
System.out.println(Thread.currentThread() + "release lock");
pro_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name + count;
System.out.println(Thread.currentThread() + "....Produce...." + this.name);
count++;
isOut = true;
consu_con.signal();
}
finally {
}
}
public void out() {
System.out.println(Thread.currentThread() + "before lock");
lock.lock();
System.out.println(Thread.currentThread() + "get lock");
try {
while (!isOut) {
try {
System.out.println(Thread.currentThread() + "release lock");
consu_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread() + "....Consume.........." + this.name);
isOut = false;
pro_con.signal();
}
finally {
//lock.unlock();
}
}
}
static class Producer implements Runnable {
Resource r;
Producer(Resource r) {
this.r = r;
}
public void run() {
while (true) {
r.set("chicken");
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable {
Resource r;
Consumer(Resource r) {
this.r = r;
}
#Override
public void run() {
while (true) {
r.out();
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
FirstOfAll, "if I lock in Resource.set() and comment out the Lock.unlock(), the code in Resource.out() can't be executed ". This statement of yours is wrong.
Let me clarify why,
In your posted code, where out() has no unlock. I assume you have no problem that one of the Consumer threads (t2 or t3) have no problem in acquiring the lock.
So lets say t2 acquired the lock, while entering out() method and didn't release the lock while exiting out() method. But you overlooked the fact that out() method is executed in infinite loop inside run() method of Consumer Runnable. So when t2 exits out(), sleep of 500 milliseconds; its still in possession of the lock. When it enters the out() method in its next iteration, it executes Lock.lock() on the same lock it already has. Since the lock is Reentrant Lock, it proceeds and executes await() where it releases the lock; and the other threads(Producer threads) waiting on the lock gets chance to acquire the lock.

java.lang.IllegalMonitorStateException when condition.wait

private static volatile AtomicInteger blockClientCount = new AtomicInteger(0);
private static Object lock = new Object();
private static Lock reentrantLock = new ReentrantLock();
private static Condition condition = reentrantLock.newCondition();
#Override
public void run() {
Random random = new Random(this.hashCode());
while (true) {
String request = random.nextInt(10) + "" + IOUtil.operators[random.nextInt(4)] + (random.nextInt(10) + 1);
System.out.println(this.getName() + " send request:" + request);
if (socketConnect()) {
BufferedReader in = null;
PrintWriter out = null;
try {
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
blockClientCount.incrementAndGet();
reentrantLock.lock();
try {
while (blockClientCount.get() % IOUtil.CLIENNT_NUM != 0) {
/**
* TODO java.lang.IllegalMonitorStateException
*/
condition.wait();
}
condition.signalAll();
} finally {
reentrantLock.unlock();
}
// synchronized (lock) {
// while (blockClientCount.get() % IOUtil.CLIENNT_NUM != 0)
// {
// lock.wait();
// }
// lock.notifyAll();
// }
out.println(request);
String response = in.readLine();
System.out.println(this.getName() + " accept response:" + response);
} catch (final Exception e) {
e.printStackTrace();
} finally {
IOUtil.close(in);
IOUtil.close(out);
}
}
try {
sleep(1000);
} catch (InterruptedException e) {
System.out.println(this.getName() + " was interrupted and stop");
IOUtil.close(socket);
break;
}
}
}
the java.lang.IllegalMonitorStateException will happen when i use ReentrantLock to wait, but it works well when i use synchronized , i can'not explain it.
The reason is that reentrantLock is unlock before condition.wait(),but i don't know why.
if someone can help me,i have submit the code to https://github.com/shanhm1991/demo_io.git
That's because you're calling the wrong method. You should call await() rather than wait() on a Condition object:
reentrantLock.lock();
try {
condition.await();
} finally {
reentrantLock.unlock();
}
You're currently calling wait which is the Object.wait() method, which requires you to be synchronized on the object that you are calling it on. But that's not what you want, you want the specific wait functionality of the Condition class, and that is only available through the method await.

release lock from object in java

hello guys this is my code , problem am facing is that despite calling notifyAll, it is not releasing the lock , can you please state the reason and tell the solution. Am new to threads. Thanks in advance.
class Lock1 {}
class Home1 implements Runnable {
private static int i = 0;
private Lock1 object;
private Thread th;
public Home1(Lock1 ob, String t) {
object = ob;
th = new Thread(this);
th.start();
}
public void run() {
synchronized (object) {
while (i != 10) {
++i;
System.out.println(i);
}
try {
// System.out.println("here");
object.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("here thread 1");
}
}
}
class Home2 implements Runnable {
private static int i = 0;
private Lock1 object;
Thread th;
public Home2(Lock1 ob, String t) {
object = ob;
th = new Thread(this);
th.start();
}
public void run() {
synchronized (object) {
while (i != 10) {
++i;
System.out.println(i);
}
try {
// System.out.println("here");
object.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("here thread 2");
}
}
}
public class Locking {
public static void main(String arg[]) {
Lock1 ob = new Lock1();
new Home1(ob, "thread 1");
new Home2(ob, "thread 2");
synchronized (ob) {
ob.notifyAll();
}
}
}
When you use notifyAll, you should also have a state changed and when you use wait, you should check that state change.
In your case it is likely that notifyAll will be called long before the threads really have time to start. (For a computer, starting a thread takes an eternity, like 10,000,000 clock cycles) This means the notifyAll is lost. (It only notifies threads which are actually waiting right at that moment)

Wait until child threads completed : Java

Problem description : -
Step 1: Take input FILE_NAME from user at main thread.
Step 2: Perform 10 operations on that file (i.e count chars, count lines etc.. ), and all those 10 operations must be in septate threads. It means there must be 10 child threads.
Step 3: Main thread waits until all those child threads completed.
Step 4: Print result.
What I did :-
I did a sample code with 3 threads. I don't want file operation code from your side.
public class ThreadTest {
// This is object to synchronize on.
private static final Object waitObject = ThreadTest.class;
// Your boolean.
private static boolean boolValue = false;
public final Result result = new Result();
public static void main(String[] args) {
final ThreadTest mytest = new ThreadTest();
System.out.println("main started");
new Thread(new Runnable() {
public void run() {
System.out.println("Inside thread");
//Int initialiser
new Thread(new Runnable() {
public void run() {
System.out.println("Setting integer value");
mytest.result.setIntValue(346635);
System.out.println("Integer value seted");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
//String initialiser
new Thread(new Runnable() {
public void run() {
System.out.println("Setting string value");
mytest.result.setStringValue("Hello hi");
System.out.println("String value seted");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
//Boolean initialiser
new Thread(new Runnable() {
public void run() {
System.out.println("Setting boolean value");
mytest.result.setBoolValue(true);
System.out.println("Boolean value seted");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
System.out.println("Thread is finished");
//Notify to main thread
synchronized (ThreadTest.waitObject) {
ThreadTest.boolValue = true;
ThreadTest.waitObject.notifyAll();
}
}
}).start();
try {
synchronized (ThreadTest.waitObject) {
while (!ThreadTest.boolValue) {
ThreadTest.waitObject.wait();
}
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("main finished");
System.out.println("Result is : " + mytest.result.toString());
}
}
Problem :-
My above code is not giving correct answer. How can I do that?
Alternate solutions:
CountDownLatch class does the same. But I don't want to use that class.
I looked this similar solution and I want to use methods of Thread only.
You can do:
Thread t = new Thread() {
public void run() {
System.out.println("text");
// other complex code
}
};
t.start();
t.join();
This way you will wait until the thread finishes and just then continue. You can join multiple threads:
for (Thread thread : threads) {
thread.join();
}
I would recommend looking at the Executors framework first, and then look into the CompletionService.
Then you can write something like this:
ExecutorService executor = Executors.newFixedThreadPool(maxThreadsToUse);
CompletionService completion = new ExecutorCompletionService(executor);
for (each sub task) {
completion.submit(new SomeTaskYouCreate())
}
// wait for all tasks to complete.
for (int i = 0; i < numberOfSubTasks; ++i) {
completion.take(); // will block until the next sub task has completed.
}
executor.shutdown();
In Java 8 a far better approach is to use parallelStream()
Note: it is far easier to see exactly what these background tasks are doing.
public static void main(String[] args) {
Stream.<Runnable>of(
() -> mytest.result.setIntValue(346635),
() -> mytest.result.setStringValue("Hello hi"),
() -> mytest.result.setBoolValue(true) )
.parallel()
.forEach(Runnable::run);
System.out.println("main finished");
System.out.println("Result is : " + mytest.result.toString());
}
I took out the debug information and the sleep as these don't alter the outcome.
You may want to choose CountDownLatch from java.util.concurrent. From JavaDocs:
A synchronization aid that allows one or more threads to wait until a
set of operations being performed in other threads completes.
Sample code:
import java.util.concurrent.CountDownLatch;
public class Test {
private final ChildThread[] children;
private final CountDownLatch latch;
public Test() {
this.children = new ChildThread[4];
this.latch = new CountDownLatch(children.length);
children[0] = new ChildThread(latch, "Task 1");
children[1] = new ChildThread(latch, "Task 2");
children[2] = new ChildThread(latch, "Task 3");
children[3] = new ChildThread(latch, "Task 4");
}
public void run() {
startChildThreads();
waitForChildThreadsToComplete();
}
private void startChildThreads() {
Thread[] threads = new Thread[children.length];
for (int i = 0; i < threads.length; i++) {
ChildThread child = children[i];
threads[i] = new Thread(child);
threads[i].start();
}
}
private void waitForChildThreadsToComplete() {
try {
latch.await();
System.out.println("All child threads have completed.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class ChildThread implements Runnable {
private final String name;
private final CountDownLatch latch;
protected ChildThread(CountDownLatch latch, String name) {
this.latch = latch;
this.name = name;
}
#Override
public void run() {
try {
// Implementation
System.out.println(name + " has completed.");
} finally {
latch.countDown();
}
}
}
public static void main(String[] args) {
Test test = new Test();
test.run();
}
}
Output:
Task 1 has completed.
Task 4 has completed.
Task 3 has completed.
Task 2 has completed.
All child threads have completed.
There are many ways to approach this. Consider CountDownLatch:
import java.util.concurrent.CountDownLatch;
public class WorkerTest {
final int NUM_JOBS = 3;
final CountDownLatch countDownLatch = new CountDownLatch(NUM_JOBS);
final Object mutex = new Object();
int workData = 0;
public static void main(String[] args) throws Exception {
WorkerTest workerTest = new WorkerTest();
workerTest.go();
workerTest.awaitAndReportData();
}
private void go() {
for (int i = 0; i < NUM_JOBS; i++) {
final int fI = i;
Thread t = new Thread() {
public void run() {
synchronized(mutex) {
workData++;
}
try {
Thread.sleep(fI * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
};
t.start();
}
}
private void awaitAndReportData() throws InterruptedException {
countDownLatch.await();
synchronized(mutex) {
System.out.println("All workers done. workData=" + workData);
}
}
}
Check if all child threads are dead, every n seconds. Simple, yet effective method:
boolean allDead=false;
while(! allDead){
allDead=true;
for (int t = 0; t < threadCount; t++)
if(threads[t].isAlive()) allDead=false;
Thread.sleep(2000);
}

Categories

Resources