import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class JI9050725 {
	// to record lock acquire/release 
	private static volatile int count = 0; 

	public static void main(String[] args) throws InterruptedException { 
		Lock lock = new ReentrantLock(); 
		Condition cond = lock.newCondition(); 

		int loop = 100; 
		for (int i = 0; i < loop; i++) { 
			// thread that can await on the condition 
			new Thread(() -> { 
				lock.lock(); 
				try { 
					count++; 
					cond.await(); 
				} catch (InterruptedException ignore) { 
				} finally { 
					lock.unlock(); 
					count--; 
				} 
			}, "succ-" + i).start(); 

			// thread that fails to await on the condition 
			new Thread(() -> { 
				boolean illegalMonitor = false; 
				try { 
					cond.awaitUninterruptibly(); 
				} catch (IllegalMonitorStateException ignore) { 
					illegalMonitor = true; 
				} finally { 
					assert illegalMonitor; 
				} 
			}, "fail-" + i).start(); 

		} 

		// make sure that all succ threads got the lock before we try to signal them. 
		while (count != loop) { 
			Thread.yield(); 
		} 

		// signal all threads and retry if count > 0 
		while (count > 0) { 
			lock.lock(); 
			try { 
				cond.signalAll(); 
			} finally { 
				lock.unlock(); 
			} 
		} 
	} 
}
