I have 2 threads, one calls get() method, another put() method.
I need to synchronize this methods in order to see result of get only after put. I do know how to do this other way, but I want to understand why am i getting .IllegalMonitorStateException with this code.
public class TransferObject {
private int value;
protected volatile boolean isValuePresent = false; //use this variable
public synchronized int get() {
synchronized (TransferObject.class) {
System.out.println("Got: " + value);
notify();
}
return value;
}
public void put(int value) {
synchronized (TransferObject.class) {
this.value = value;
System.out.println("Put: " + value);
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Here is example of 2 threads.
public class ConsumerTask implements Runnable {
private TransferObject transferObject;
protected volatile boolean stopped;
public ConsumerTask(TransferObject transferObject) {
this.transferObject = transferObject;
new Thread(this, "ConsumerTask").start();
}
public void run() {
while (!stopped) {
transferObject.get();
}
}
public void stop() {
stopped = true;
}
}
public class ProducerTask implements Runnable {
private TransferObject transferObject;
protected volatile boolean stopped;
static volatile AtomicInteger i = new AtomicInteger(0);
public ProducerTask(TransferObject transferObject) {
this.transferObject = transferObject;
new Thread(this, "ProducerTask").start();
}
public void run() {
while (!stopped) {
transferObject.put(i.incrementAndGet());
}
}
public void stop() {
stopped = true;
}
}
You have two threads and one object for locking TransferObject.class.
When your thread ConsumerTask gets the lock, object TransferObject.class don't have sleeping threads, and when you call notify() for this monitor you get IllegalMonitorStateException
From the description for method notify:
Wakes up a single thread that is waiting on this object's monitor.
You don't have waiting treads for monitor TransferObject.class
Related
So I implanted Mutex to pause and resume thread but when I start the thread with the implemented Mutex outer thread stop executing till the inner thread finish. I am not sure where I am wrong. I create an interface to get the lock value and use it as boolean for if statement. So basically when the custom thread run the inner thread freeze till the inner thread is not finished. I need to not stop.In two words, I need to pause the thread and resume it later. In // do my code here comment field I am using function which have a loop inside, I am not sure if this is the problem.
Interface:
public interface Thread {
Mutex getMutex();
void run();
}
Thread example:
public class CustomThread extends Thread implements ThreadInterface{
private final Mutex mutex;
public CustomeThread() {
this.mutex = new Mutex(false);
}
public Mutex getMutex() {
return this.mutex;
}
#Override
public void run() {
while (!isInterrupted()) {
mutex.step();
// Do my code here
}
}
}
Starting the thread in another thread:
public class ThreadingUtil {
public void threadRunner(List<CustomThread> threadList) throws InterruptedException {
if (threadList.size() > 1) {
Random random = new Random();
while(threadList.size() > 0) {
int index = random.nextInt(threadList.size());
CustomThread thread = threadList.get(0);
if(thread.getMutex().isLock().get()) {
thread.getMutex().unlock();
} else {
thread.run();
}
// Code stop here after run the thread
Thread.sleep(20000);
thread.getMutex().lock();
System.out.println("thread mus be locked next thread");
}
}
}
Running outer thread:
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
threadingUtil.threadRunner(threadList);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread.start();
Mutex:
public class Mutex {
private final AtomicBoolean lock;
private final Object mutex;
public Mutex(boolean lock) {
this.lock = new AtomicBoolean(lock);
this.mutex = new Object();
}
public void step() {
if (lock.get()) synchronized (mutex) {
try {
mutex.wait();
} catch (InterruptedException ex) {
}
}
}
public void lock() {
lock.set(true);
}
public AtomicBoolean isLock() {
return this.lock;
}
public void unlock() {
lock.set(false);
synchronized (mutex) {
mutex.notify();
}
}
}
EDIT: I start the thread with implementing start() method in the Thread interface now its not blocking the thread but the getMutex().lock() is not stopping the thread now.
EDIT: in run method make sure to not place inner loop i the while loop since is not pausing the inner loop
I have this code:
public class UsbDrive extends HardDrive {
private Date lastUpdate;
private void updateDate() {
lastUpdate = new Date();
}
public synchronized void cutAndPaste(UsbDrive other, int originAddress, int destAddress) {
byte[] data = read(originAddress);
boolean success = other.write(data, destAddress);
if (success) {
erase(originAddress);
updateDate();
} else {
throw new RuntimeException("Write failed!");
}
}
}
class HardDrive {
...
public synchronized byte[] read(int address) {...}
public synchronized boolean write(byte[] data, int address) {...}
public synchronized void erase(int address) {...}
...
I'm trying to simulate a deadlock
public class Main {
private static UsbDrive usb1 = new UsbDrive();
private static UsbDrive usb2 = new UsbDrive();
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(new ThreadA());
Thread thread2 = new Thread(new ThreadB());
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
static class ThreadA implements Runnable {
#Override
public void run() {
try {
Thread.sleep(5000);
}
catch (Exception e) {
e.printStackTrace();
}
synchronized (usb1) {
usb1.cutAndPaste(usb2, 1, 2);
}
}
}
static class ThreadB implements Runnable {
#Override
public void run() {
synchronized (usb2) {
usb2.cutAndPaste(usb1, 1, 2);
}
}
}
}
However deadlock doesn't happen - why? ThreadA calls method cutAndPaste() locked on usb1, while inside that method write() is called which is locked on usb2
Shouldn't deadlock occur?
How should I change the code to trigger deadlock?
I get this output:
reading data
Erasing data
reading data
Erasing data
It is a race condition that decides whether the deadlock happens or not as far as I can see, one good option to make the deadlock more likely to happen is a loop, but an easier option might be to insert Thread.sleep(5000); between byte[] data = read(originAddress); and boolean success = other.write(data, destAddress); in UsbDrive::cutAndPaste. EDIT: And remove the existing Thread.sleep(5000);.
EDIT: Clarified answer.
EDIT2: I just ran the code with the changes, and it indeed induces a deadlock now:
import java.util.Date;
public class Main {
private static UsbDrive usb1 = new UsbDrive();
private static UsbDrive usb2 = new UsbDrive();
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(new ThreadA());
Thread thread2 = new Thread(new ThreadB());
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
static class ThreadA implements Runnable {
#Override
public void run() {
synchronized (usb1) {
usb1.cutAndPaste(usb2, 1, 2);
}
}
}
static class ThreadB implements Runnable {
#Override
public void run() {
synchronized (usb2) {
usb2.cutAndPaste(usb1, 1, 2);
}
}
}
}
class UsbDrive extends HardDrive {
private Date lastUpdate;
private void updateDate() {
lastUpdate = new Date();
}
public synchronized void cutAndPaste(UsbDrive other, int originAddress, int destAddress) {
byte[] data = read(originAddress);
try {
Thread.sleep(5000);
}
catch (Exception e) {
e.printStackTrace();
}
boolean success = other.write(data, destAddress);
if (success) {
erase(originAddress);
updateDate();
} else {
throw new RuntimeException("Write failed!");
}
}
}
class HardDrive {
public synchronized byte[] read(int address) {return new byte[]{};}
public synchronized boolean write(byte[] data, int address) {return true;}
public synchronized void erase(int address) {}
}
I encountered the issue like the Deadlocks and Synchronized methods. In this case, methodA, methodB, A.last() all must be the synchronized method. So I am going to resolve this issue by removing synchronized in the method B.last(). Any deadlock in this solution? Could you please let me know any solution to resolve this better?
Class A
{
synchronized void methodA(B b)
{
b.last();
}
synchronized void last()
{
System.out.println(“ Inside A.last()”);
}
}
Class B
{
synchronized void methodB(A a)
{
a.last();
}
synchronized void last()
{
System.out.println(“ Inside B.last()”);
}
}
Class Deadlock implements Runnable
{
A a = new A();
B b = new B();
// Constructor
Deadlock()
{
Thread t = new Thread(this);
t.start();
a.methodA(b);
}
public void run()
{
b.methodB(a);
}
public static void main(String args[] )
{
new Deadlock();
}
}
In general, to avoid deadlocks, either use only one lock at all, or make sure that locks are always acquired in the same order.
Assuming that you decide A always has to be locked before B, a minimally invasive bugfix for your example (assuming that nothing else synchronizes against A or B objects) would be this in class B:
void methodB(A a) {
synchronized(a) {
synchronized(this) {
// do whatever was in methodB before, including...
a.last();
}
}
}
That way, if both locks are required, lock of A is always acquired first, causing no deadlocks.
You can also do the same with the Java 5+ java.util.concurrent locks. Removing a synchronized where not needed is of course also an option to solve the deadlock (but if synchronization was needed, it will cause race conditions instead which are usually worse than a deadlock).
You can use a common mutex such as a ReentrantLock or synchronized blocks between the two methods instead of synchronized.
ReentrantLock example:
Class A
{
A(Lock lock) {
this.lock = lock;
}
private Lock lock;
void methodA(B b)
{
lock.lock();
try {
b.last();
} finally {
lock.unlock();
}
}
void last()
{
lock.lock();
try {
System.out.println(“ Inside A.last()”);
} finally {
lock.unlock();
}
}
}
Class B
{
B(Lock lock) {
this.lock = lock;
}
private Lock lock;
void methodB(A a)
{
lock.lock();
try {
a.last();
} finally {
lock.unlock();
}
}
void last()
{
lock.lock();
try {
System.out.println(“ Inside B.last()”);
} finally {
lock.unlock();
}
}
}
Class Deadlock implements Runnable
{
Lock lock = new ReentrantLock();
A a = new A(lock);
B b = new B(lock);
// Constructor
Deadlock()
{
Thread t = new Thread(this);
t.start();
a.methodA(b);
}
public void run()
{
b.methodB(a);
}
public static void main(String args[] )
{
new Deadlock();
}
}
synchronized block example:
Class A
{
A(Object lock) {
this.lock = lock;
}
private Object lock;
void methodA(B b)
{
synchronized(lock){
b.last();
}
}
void last()
{
synchronized(lock){
System.out.println(“ Inside A.last()”);
}
}
}
Class B
{
B(Object lock) {
this.lock = lock;
}
private Object lock;
void methodB(A a)
{
synchronized(lock){
a.last();
}
}
void last()
{
synchronized(lock){
System.out.println(“ Inside B.last()”);
}
}
}
Class Deadlock implements Runnable
{
Object lock = new Object();
A a = new A(lock);
B b = new B(lock);
// Constructor
Deadlock()
{
Thread t = new Thread(this);
t.start();
a.methodA(b);
}
public void run()
{
b.methodB(a);
}
public static void main(String args[] )
{
new Deadlock();
}
}
I have implemented a Non Reentrant Lock. I want to know if this has any mistakes, race conditions etc. I am aware of the fact that existing libraries have to be used (instead of writing our own), but this is just to see if I am understanding the java concurrency correctly. Any feedback is appreciated.
public class MyLock {
private boolean isLocked = false;
private long owner = -1;
private static String TAG = "MyLock: ";
public synchronized void Lock() throws InterruptedException, IllegalStateException {
if(!isLocked) {
isLocked = true;
owner = Thread.currentThread().getId();
} else {
if(owner == Thread.currentThread().getId()) {
throw new IllegalStateException("Lock already acquired. " +
"This lock is not reentrant");
} else {
while(isLocked == true) {
System.out.println(TAG+"Waiting for Lock, Tid = " +
Thread.currentThread().getId());
wait();
}
}
}
System.out.println(TAG+"Lock Acquired: Owner = " + owner);
}
public synchronized void Unlock() throws IllegalStateException {
if(!isLocked || owner != Thread.currentThread().getId()) {
throw new IllegalStateException("Only Owner can Unlock the lock");
} else {
System.out.println(TAG+"Unlocking: Owner = " + owner);
owner = -1;
isLocked = false;
notify();
}
}
}
Here is an implementation of a "standard" / "non-reentrant" lock in Java, as a wrapper around Java's built-in ReentrantLock that simply prevents the lock from ever being acquired more than once.
/**
* A "non-reentrant" lock, implemented as a wrapper around Java's ReentrantLock.
*
*/
class StandardLock implements java.util.concurrent.locks.Lock {
public static class LockAlreadyHeldException extends RuntimeException {}
private final java.util.concurrent.locks.ReentrantLock mainLock;
private void checkNotAlreadyHeld() {
if (mainLock.getHoldCount()!=0) {
throw new LockAlreadyHeldException();
}
}
public StandardLock() {
mainLock=new java.util.concurrent.locks.ReentrantLock();
}
public StandardLock(boolean fair) {
mainLock=new java.util.concurrent.locks.ReentrantLock(fair);
}
#Override
public void lock() {
checkNotAlreadyHeld();
mainLock.lock();
}
#Override
public void lockInterruptibly() throws InterruptedException {
checkNotAlreadyHeld();
mainLock.lockInterruptibly();
}
#Override
public boolean tryLock() {
checkNotAlreadyHeld();
return mainLock.tryLock();
}
#Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
checkNotAlreadyHeld();
return mainLock.tryLock(time, unit);
}
#Override
public void unlock() {
mainLock.unlock();
}
#Override
public Condition newCondition() {
return mainLock.newCondition();
}
}
The advantages to this approach are that the class implements Java's Lock interface, and Condition Variables thus come with it in order to allow the creation of Monitors. Monitors are important in order to fully leverage locks for concurrent programming.
I have multiple consumer threads waiting on a CountDownLatch of size 1 using await(). I have a single producer thread that calls countDown() when it successfully finishes.
This works great when there are no errors.
However, if the producer detects an error, I would like for it to be able to signal the error to the consumer threads. Ideally I could have the producer call something like abortCountDown() and have all of the consumers receive an InterruptedException or some other exception. I don't want to call countDown(), because this requires all of my consumer threads to then do an additional manual check for success after their call to await(). I'd rather they just receive an exception, which they already know how to handle.
I know that an abort facility is not available in CountDownLatch. Is there another synchronization primitive that I can easily adapt to effectively create a CountDownLatch that supports aborting the countdown?
JB Nizet had a great answer. I took his and polished it a little bit. The result is a subclass of CountDownLatch called AbortableCountDownLatch, which adds an "abort()" method to the class that will cause all threads waiting on the latch to receive an AbortException (a subclass of InterruptedException).
Also, unlike JB's class, the AbortableCountDownLatch will abort all blocking threads immediately on an abort, rather than waiting for the countdown to reach zero (for situations where you use a count>1).
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class AbortableCountDownLatch extends CountDownLatch {
protected boolean aborted = false;
public AbortableCountDownLatch(int count) {
super(count);
}
/**
* Unblocks all threads waiting on this latch and cause them to receive an
* AbortedException. If the latch has already counted all the way down,
* this method does nothing.
*/
public void abort() {
if( getCount()==0 )
return;
this.aborted = true;
while(getCount()>0)
countDown();
}
#Override
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
final boolean rtrn = super.await(timeout,unit);
if (aborted)
throw new AbortedException();
return rtrn;
}
#Override
public void await() throws InterruptedException {
super.await();
if (aborted)
throw new AbortedException();
}
public static class AbortedException extends InterruptedException {
public AbortedException() {
}
public AbortedException(String detailMessage) {
super(detailMessage);
}
}
}
Encapsulate this behavior inside a specific, higher-level class, using the CountDownLatch internally:
public class MyLatch {
private CountDownLatch latch;
private boolean aborted;
...
// called by consumers
public void await() throws AbortedException {
latch.await();
if (aborted) {
throw new AbortedException();
}
}
// called by producer
public void abort() {
this.aborted = true;
latch.countDown();
}
// called by producer
public void succeed() {
latch.countDown();
}
}
You can create a wrapper around CountDownLatch that provides the ability to cancel the waiters. It will need to track the waiting threads and release them when they timeout as well as remember that the latch was cancelled so future calls to await will interrupt immediately.
public class CancellableCountDownLatch
{
final CountDownLatch latch;
final List<Thread> waiters;
boolean cancelled = false;
public CancellableCountDownLatch(int count) {
latch = new CountDownLatch(count);
waiters = new ArrayList<Thread>();
}
public void await() throws InterruptedException {
try {
addWaiter();
latch.await();
}
finally {
removeWaiter();
}
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
try {
addWaiter();
return latch.await(timeout, unit);
}
finally {
removeWaiter();
}
}
private synchronized void addWaiter() throws InterruptedException {
if (cancelled) {
Thread.currentThread().interrupt();
throw new InterruptedException("Latch has already been cancelled");
}
waiters.add(Thread.currentThread());
}
private synchronized void removeWaiter() {
waiters.remove(Thread.currentThread());
}
public void countDown() {
latch.countDown();
}
public synchronized void cancel() {
if (!cancelled) {
cancelled = true;
for (Thread waiter : waiters) {
waiter.interrupt();
}
waiters.clear();
}
}
public long getCount() {
return latch.getCount();
}
#Override
public String toString() {
return latch.toString();
}
}
You could roll your own CountDownLatch out using a ReentrantLock that allows access to its protected getWaitingThreads method.
Example:
public class FailableCountDownLatch {
private static class ConditionReentrantLock extends ReentrantLock {
private static final long serialVersionUID = 2974195457854549498L;
#Override
public Collection<Thread> getWaitingThreads(Condition c) {
return super.getWaitingThreads(c);
}
}
private final ConditionReentrantLock lock = new ConditionReentrantLock();
private final Condition countIsZero = lock.newCondition();
private long count;
public FailableCountDownLatch(long count) {
this.count = count;
}
public void await() throws InterruptedException {
lock.lock();
try {
if (getCount() > 0) {
countIsZero.await();
}
} finally {
lock.unlock();
}
}
public boolean await(long time, TimeUnit unit) throws InterruptedException {
lock.lock();
try {
if (getCount() > 0) {
return countIsZero.await(time, unit);
}
} finally {
lock.unlock();
}
return true;
}
public long getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
public void countDown() {
lock.lock();
try {
if (count > 0) {
count--;
if (count == 0) {
countIsZero.signalAll();
}
}
} finally {
lock.unlock();
}
}
public void abortCountDown() {
lock.lock();
try {
for (Thread t : lock.getWaitingThreads(countIsZero)) {
t.interrupt();
}
} finally {
lock.unlock();
}
}
}
You may want to change this class to throw an InterruptedException on new calls to await after it has been cancelled. You could even have this class extend CountDownLatch if you needed that functionality.
Since Java 8 you can use CompletableFuture for this. One or more threads can call the blocking get() method:
CompletableFuture<Void> cf = new CompletableFuture<>();
try {
cf.get();
} catch (ExecutionException e) {
//act on error
}
another thread can either complete it successfully with cf.complete(null) or exceptionally with cf.completeExceptionally(new MyException())
There is a simple option here that wraps the CountDownLatch. It's similar to the second answer but does not have to call countdown repeatedly, which could be very expensive if the latch is for a large number. It uses an AtomicInteger for the real count, with a CountDownLatch of 1.
https://github.com/scottf/CancellableCountDownLatch/blob/main/CancellableCountDownLatch.java
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class CancellableCountDownLatch {
private final AtomicInteger count;
private final CountDownLatch cdl;
public CancellableCountDownLatch(int count) {
this.count = new AtomicInteger(count);
cdl = new CountDownLatch(1);
}
public void cancel() {
count.set(0);
cdl.countDown();
}
public void await() throws InterruptedException {
cdl.await();
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
return cdl.await(timeout, unit);
}
public void countDown() {
if (count.decrementAndGet() <= 0) {
cdl.countDown();
}
}
public long getCount() {
return Math.max(count.get(), 0);
}
#Override
public String toString() {
return super.toString() + "[Count = " + getCount() + "]";
}
}