ReentrantLock condition wait get IllegalMonitorStateException in java - java

My application will keep monitoring a folder, once it is not empty, it will wake up the worker thread. IllegalMonitorStateException will be thrown in the wait .
what is the reason ?
import java.io.File;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.io.FileUtils;
public class LockTest {
public static void main(String[] args) {
String folder = "C:\\temp\\test";
final ReentrantLock messageArrivedLock = new ReentrantLock();
final Condition messageArrivedCondition = messageArrivedLock.newCondition();
Thread workerThread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("worker thread is running");
messageArrivedLock.lock();
while (true) {
System.out.println("worker thread is waiting");
try {
messageArrivedCondition.wait(); //Exception here
System.out.println("worker thread wakes up");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (messageArrivedLock.isHeldByCurrentThread()) {
messageArrivedLock.unlock();
}
}
}
}
});
workerThread.start();
while (true) {
long size = FileUtils.sizeOf(new File(folder));
System.out.println("size:" + size); // 1000
messageArrivedLock.lock();
try {
if (size > 0) {
messageArrivedCondition.signalAll();
}
} finally {
if (messageArrivedLock.isHeldByCurrentThread()) {
messageArrivedLock.unlock();
}
}
}
}
}

I'm going to assume you meant to invoke Condition#await, which will typically (as is the case here) have the same behavior you experienced with Object#wait.
The current thread is assumed to hold the lock associated with this
Condition when this method is called. It is up to the implementation
to determine if this is the case and if not, how to respond.
Typically, an exception will be thrown (such as
IllegalMonitorStateException) and the implementation must document
that fact.
Presumably your while loop iterated once, released the lock inside the finally. On its second iteration, your thread doesn't have the lock, so calling wait will throw the IllegalMonitorStateException. Your thread needs to own the lock to invoke await on the associated Condition.
You can acquire the lock within the while loop.

Related

Synchronized block still locked after thread restart

I try to restart thread but synchronized block in thread keep locked after restarted. I shouldn't change socket properties because some processes take too long but when network connection lost it hangs forever. I try to use InterruptedException but it doesn't work. Is there any way to release this lock?
public static void main(String[] args) {
try {
synchronizedBlock t1 = new synchronizedBlock();
t1.start();
Thread.sleep(500);
t1.cancel();
t1 = new synchronizedBlock();
t1.start();
} catch (Exception e) {
e.printStackTrace();
}
while (true) {
}
}
public class synchronizedBlock extends Thread {
boolean isRunning = true;
boolean isRunning2 = true;
public static Object[] locks = new Object[5];
public synchronizedBlock() {
for (Integer i = 0; i < 5; i++) {
synchronizedBlock.locks[i] = i;
}
}
public void cancel() {
isRunning = false;
interrupt();
}
public void socketProces() {
while (isRunning2) {
}
}
public void proces(int index) {
try {
synchronized (locks[index]) {
System.out.println("Synchronized Block Begin");
socketProces();
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
System.out.println("Run begin");
while (isRunning) {
proces(1);
}
Thread.sleep(1);
} catch (InterruptedException e) {
//Do Something
} catch (Exception e) {
e.printStackTrace();
}
}
}
Result:
Run begin
Synchronized Block Begin
Run begin
When you start the synchronizedBlock thread you'll get a stack trace like this I think:
run -> proces -> socketProcess.
Then because isRunning2 = true, the thread will enter an infinite loop in socketProcess and never terminate.
Keep in mind that in Java there is no such thing as 'restarting' a thread. Once started, a thread can never be restarted. Indeed, you are creating two sycnchronizedBlock objects, not restarting a single object.
As a side note, it is generally problematic to overwrite static state in a class constructor, as you're doing with the locks variable, without synchronization.
The issue here is the Integer cache which is used in the for loop to initialize the synchronizedBlock.locks array:
for (Integer i = 0; i < 5; i++) {
synchronizedBlock.locks[i] = i;
}
When this code is run again, due to the constructor of the second synchronizedBlock, the synchronizedBlock.locks array contains the same Integer instances which where created when this for loop was executed for the first time. This means that the synchronized (locks[index]) lock will be on the same Integer object. As you have already one thread holding the lock for the Integer(1) object, the second thread waits outside the lock waiting for it to be released.
This is also problematic in combination with the fact that the first thread is not terminating. Your method
public void socketProces() {
while (isRunning2) {
}
}
is an endless loop as you don't change the value of isRunning2, ever. Also, the interrupt() method itself does not stop any thread. Instead, it sets just an internal flag in the Thread class, which can be checked with isInterrupted() and interrupted(). You have to check this flag and react on it like "Oh, someone wants me to stop, so I stop now".
To solve your problem you should at least quit your thread when the "isInterrupted" flag of the Thread instance is set. You can do it like this:
public void socketProces() {
while (isRunning2) {
if (Thread.interrupted()) {
return;
}
}
}
Instead of returning from socketProces() normally you could throw an InterruptedException like other methods do.
Also, depending on how you want to initialize/use the instances you want to lock on with synchronized(...), you might want to consider on how you create/fill the synchronizedBlock.locks array and which objects you want to use (the Integer cache might be problematic here). It depends on you if the creation of a new synchronizedBlock instance will/should/shouldn't create new objects to lock on in the synchronizedBlock.locks array.

What exactly gets locked when using APIs in java.util.concurrent.Locks?

This is probably a very silly question. I am reading through the documentation of interfaces and classes in packages java.util.concurrent.atomic and java.util.concurrent.locks. I find everywhere that
void lock() – acquire the lock if it’s available; if the lock isn’t available a thread gets blocked until the lock is released
What I am not sure about is, what resource is exactly getting locked? The code snippet examples show
Lock lock = new ReentrantLock();
lock.lock();
try {
// access to the shared resource
} finally {
lock.unlock();
}
Does whatever that is used under the call of lock() get locked? How does JVM know that before getting to that line? And what if there are multiple resources between lock() and unlock()? I guess I am having this question because I am reading this right after reading synchronization and it has very specific way of saying what to lock - like: synchronized(resourceReferenceThatNeedsToBeLocked)
I reseached a lot and yet can't find answer for this question.
You can think of your code like an optimised version of synchronized. You are "synchronizing" on your lock object, but in a more efficient way.
Note that when you're using synchronized, there are no guarantees regarding the resources used inside of the synchronized block. You are just locking on a specific object, which may or may not be the same resources you are using inside of the synchronized block. In essence, regardless of lock or synchronized, you're just saying "make sure no other thread can access the code (or other code guarded by the same lock or ´synchronized´ on the same instance) inside of this block until I'm finished".
The key thing to understand, regardless of lock or synchronized, is that you're guarding a block of code from concurrent access. The code inside the block may access one or several different resources; if the same resources are used elsewhere, access to them needs to be guarded with the same lock or be synchronized on the same instance in order to be safe.
Lock is always associated with data. If there's no data, synchronization is pointless. You have object Thread, Lock, Condition and so on. And then you have data structure that is synchronized with the help of this objects. You need full example. In sample bellow, I'm synchronizing a queue, so that data added to it is always synchronized. Of course it's added to queue from different threads
import java.util.Deque;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class BackgroundWorker {
private Worker worker;
private StringBuilder allData;
#Before
public void setUp() throws Exception {
worker = new Worker(allData); // start databse worker
worker.start();
}
#After
public void tearDown() throws Exception {
worker.stop();
}
public void logValue(final String data) {
final LogValue logValue = new LogValue(data);
worker.queue(logValue);
}
#Test
public void test() {
// very dummy, NOT multithreaded test
for (int i = 0; i < 10; i++) {
logValue("Some data " + i);
}
}
private static class Worker implements Runnable {
private static final int MAX_QUEUE_SIZE = 1000;
private final Deque<Job> queue = new LinkedList<Job>();
private final Lock lock = new ReentrantLock();
private final Condition jobAdded = lock.newCondition();
private final Condition jobRemoved = lock.newCondition();
private final StringBuilder dataSource;
private final AtomicBoolean running = new AtomicBoolean(false);
private Thread thread = null;
Worker(final StringBuilder dataSource) {
this.dataSource = dataSource;
}
#Override
public void run() {
processing: for (;;) {
Job job;
lock.lock();
try {
while (null == (job = queue.pollFirst())) {
if (!running.get()) break processing;
try {
jobAdded.await();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
jobRemoved.signal();
}
finally {
lock.unlock();
}
job.run(dataSource);
}
}
void start() {
lock.lock();
try {
if (running.getAndSet(true)) return; // already running
thread = new Thread(this, "Database worker");
thread.start();
}
finally {
lock.unlock();
}
}
void stop() {
Thread runningThread;
lock.lock();
try {
if (!running.getAndSet(false)) return; // already stopped
runningThread = thread;
thread = null;
jobAdded.signal();
}
finally {
lock.unlock();
}
// wait for the thread to finish while not holding a lock
try {
runningThread.join(2000); // we give it 2 seconds to empty its queue
} catch (InterruptedException e) {
e.printStackTrace();
}
runningThread.interrupt(); // we interrupt it just in case it hasn't finished yet
}
void queue(final Job job) {
if (!running.get()) throw new IllegalStateException("Worker thread is not running");
lock.lock();
try {
while (queue.size() >= MAX_QUEUE_SIZE) {
try {
jobRemoved.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.addLast(job);
jobAdded.signal();
}
finally {
lock.unlock();
}
}
}
private static interface Job {
void run(StringBuilder dataSource);
}
private static class LogValue implements Job {
final String myData;
LogValue(final String data) {
this.myData = data;
}
#Override
public void run(final StringBuilder dataSource) {
dataSource.append(this.myData);
}
}
}
To answer my question:
The object that is locked is the object that reference variable lock is referring to. In this case a ReentrantLock object.
An important thing to note:
The code above is potentially misguiding. Creating a new lock object in a method would be done by respective threads, and the respective thread will only lock that was created in it's stack. If you want to lock a particular instance's variables or methods, that instance should have its own lock object and only that same lock object should be used for synchronisation.
Refer this question for more info. Refer this documentation of the lock in question.

worker thread is not notified in multithread code

I want to write a traditional producer and consumer multithread program in Java. Producer thread will send message to thread-safe List until this list get full. once buffer is full, it will notify worker thread and buffer will be cleared. In my coding, the worker thread is not notified.
Do you know the reason ? Thanks.
package com;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadTest {
public static void main(String[] args) {
final List<String> bufferSafeList = Collections.synchronizedList(new ArrayList<String>());
final ReentrantLock bufferLock = new ReentrantLock();
final Condition bufferFull = bufferLock.newCondition();
// final Condition bufferEmpty = bufferLock.newCondition();
Thread producerThread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
bufferLock.lock();
bufferSafeList.add(System.currentTimeMillis() + "");
System.out.println("add to buffer " + bufferSafeList.size());
if (bufferSafeList.size() > 100) {
System.out.println("send wake up signal");
bufferFull.signalAll();
//waiting for buff cleared
while(!bufferSafeList.isEmpty()){
Thread.sleep(1000);
}
}
Thread.sleep(1000);
} catch(Exception e){
e.printStackTrace();
}
finally {
bufferLock.unlock();
}
}
}
});
producerThread.start();
Thread workerThread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
bufferLock.lock();
System.out.println("waiting for wakeup signal");
bufferFull.await();
System.out.println("clear buffer");
bufferSafeList.clear();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
bufferLock.unlock();
}
}
}
});
workerThread.start();
}
}
You only unlock the bufferLock in the finally, so the workerThread will never be able to progress further than trying to obtain the lock
When the buffer is full unlock so that the workerThread can continue
If the producer thread happens to run first, as it is likely to do because it is started first, it will likely lock bufferLock first, in which case it will fill the list and invoke bufferFull.signalAll() while the consumer is still waiting to acquire the lock. You then busy-wait for the worker to clear the list, which it never will do because it cannot proceed.
Moreover, even if you unlocked the lock after signalling, that would be too late. By the time the worker is await()ing the condition, the signal has already come and gone. Indeed, there is a race condition there even if the producer waits to acquire the lock until it is ready to signal.
The correct usage of a condition variable always involves testing whether the expected condition is satisfied before waiting, and looping back to wait some more if it is not satisfied after resuming from the wait. You can overcome the race in your code by implementing this.

Thread synchronization with Locks and Conditions

I have a problem to understand Locks and Conditions in Java, i do not understand why my code ends up in a deadlock. My programm consists of a Mainthread and a Subthread, subthread is a member of Mainthread. Both threads run in an infinite loop, Subthread's loop is supposed to execute exactly one iteration as soon as it receives the signal for startCond from the Mainthread. Mainthread should wait for the finishCond signal to continue.
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
public static void main(String[] args) {
LockTest lt = new LockTest();
Mainthread m1 = lt.new Mainthread();
m1.start();
}
public class Mainthread extends Thread {
private Subthread sub = new Subthread();
public void run(){
System.out.println("Main start");
sub.start();
while(!isInterrupted()) {
try {
sub.getStartLock().lock();
sub.getStartCond().signal();
sub.getStartLock().unlock();
sub.getFinishLock().lock();
sub.getFinishCond().await();
sub.getFinishLock().unlock();
System.out.println("Main done");
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Subthread extends Thread {
private Lock startLock = new ReentrantLock();
private Lock finishLock = new ReentrantLock();
private Condition startCond = startLock.newCondition();
private Condition finishCond = finishLock.newCondition();
public Lock getStartLock() {
return startLock;
}
public Lock getFinishLock() {
return finishLock;
}
public Condition getStartCond() {
return startCond;
}
public Condition getFinishCond() {
return finishCond;
}
public void run() {
System.out.println("Sub start");
while(!isInterrupted()) {
try {
startLock.lock();
startCond.await();
startLock.unlock();
finishLock.lock();
finishCond.signal();
finishLock.unlock();
System.out.println("Sub done");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
My expected output would be:
Main done Sub done
(repeated as many times as it was executed in the loops).
Is there a way to solve this problem easier?
The main thread starts, it creates new sub thread and starts it but calling start on a thread does not mean that the thread would receive the processor imeddiatly and that its code will be actually executed.
Main, callss sub.getStartCond().signal(); but at this moment the sub thread is still not running so it misses this signal.
Main, awaits on the finishCond.
Sub starts executing its run method, it goes to the start condition and waits on it for ever.
The deadlock.
Signal wakes up only CURRENTLY waiting thread, it does not 'remember' previous calls.
Use Semaphore instead http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html
it has the semantic of 'counting the permits'.
There might be a more reliable way to do this. I would recommend using a CountDownLatch initialized with a count of 1, instead of a condition. Both the main and child threads can share the same instance of the latch (since the main owns the child that should be easy). The child will call await() and the main will call countDown() when you need to send the signal to the child. I recommend you make the latch private and final.
class ChildThread extends Thread {
private final CountDownLatch signal;
public ChildThread(CountDownLatch signal) {
this.signal = signal;
}
public void run() {
// The loop is necessary in case we get interrupted.
while (true) {
try {
signal.await();
break;
} catch(InterruptedException ignored) {
}
}
// do the work...
}
}
class MainThread extends Thread {
private final ChildThread child;
private final CountDownLatch signalToChild;
public MainThread() {
signalToChild = new CountDownLatch(1);
child = new ChildThread(signalToChild);
}
public void run() {
// I can start the child right away but I'd rather make sure it
// starts if the main thread has started.
child.start();
// prework
// let's signal the child
signalToChild.countDown();
// now the child is working, let's go on with the main thread work
}
}
This works because main and child thread actually share state, i.e., the latch. It does not matter if the main thread decrements the latch before the child thread is actually started, because the child will check this shared state to know if it can start.

How to wait for specified time in critical section locked by ReentrantLock?

I need to stop thread somehow for 1 sec while thread is in critical section locked by ReentrantLock.
My code is :
public class Lock implements Runnable {
private ReentrantLock lock = new ReentrantLock();
#Override
public void run() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " is running !");
lock.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
Lock lock = new Lock();
Thread thread = new Thread(lock);
thread.start();
}
}
When I call lock.wait(1000) in run() method it throws IllegalMonitorStateException.
Why is this exception if I obtained monitor by lock.lock() method?
The same happens when I call super.wait(1000) instead of lock.wait(1000).
You get the exception when calling lock.wait(1000) inside the lock b/c you haven't got the object locked in the right way. It's a thing.
synchronized(object) {
object.wait(1000);
}
That works b/c you have the object's monitor locked. ReentrantLock.lock() works in a different way. All is not lost! You can use Thread.sleep() or LockSupport.parkNanos() to put your thread to sleep inside the critical section.
If you need to handle spurious wakeup, you'll want a loop.
long waitStart = System.nanoTime();
long waitTime = TimeUnit.SECONDS.toNanos(1);
do {
LockSupport.parkNanos(waitTime);
waitTime = waitTime - (System.nanoTime() - waitStart);
} while(waitTime > 0);
Or some variation of the above.
Good luck.

Categories

Resources