I am unable to understand why the code mentioned in the listing 8.3 in the book is not deadlock prone. When I run the code, it doesn't leads to deadlock. I took the idea from the book and modified the code.
Below is the program:-
public class LockOrderingDeadLockSolved {
private final Object left = new Object();
private final Object right = new Object();
private final Object tieLock = new Object();
public static void main(String[] args) {
LockOrderingDeadLockSolved obj = new LockOrderingDeadLockSolved();
int leftHash = System.identityHashCode(obj.left);
int rightHash = System.identityHashCode(obj.right);
System.out.println(leftHash +" --- " + rightHash);
Thread t = new Thread() {
public void run() {
if (leftHash < rightHash)
obj.leftRight();
else if (leftHash > rightHash)
obj.rightLeft();
else
obj.tieLockMethod();
}
};
Thread t1 = new Thread() {
public void run() {
if (leftHash < rightHash)
obj.leftRight();
else if (leftHash > rightHash)
obj.rightLeft();
else
obj.tieLockMethod();
}
};
t.start();
t1.start();
}
private void leftRight() {
synchronized (left) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (right) {
System.out.println("Left right -- left right lock");
}
}
}
private void rightLeft() {
synchronized (right) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (left) {
System.out.println("Right left -- right left lock");
}
}
}
private void tieLockMethod() {
synchronized (tieLock) {
synchronized (left) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (right) {
System.out.println("Right left --- tie lock");
}
}
}
}
}
Output:-
865113938 --- 1442407170
Left right -- left right lock
Left right -- left right lock
Deadlock prone program:-
public class LockOrderingDeadLock {
private final Object left = new Object();
private final Object right = new Object();
public static void main(String[] args) {
LockOrderingDeadLock obj = new LockOrderingDeadLock();
Thread t = new Thread() {
public void run() {
obj.leftRight();
}
};
Thread t1 = new Thread() {
public void run() {
obj.rightLeft();
}
};
t.start();
t1.start();
}
private void leftRight() {
synchronized (left) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (right) {
System.out.println("Left right");
}
}
}
private void rightLeft() {
synchronized (right) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (left) {
System.out.println("Right left");
}
}
}
}
If the locks are acquired in the same order the deadlock won't happen.
To make your example deadlock you have to repeatedly acquire the same locks in a different order. This can be done with the following code.
private static final Object left = new Object();
private static final Object right = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
synchronized (left) {
synchronized (right) {
System.out.println("Left right -- left right lock");
}
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
synchronized (right) {
synchronized (left) {
System.out.println("Right left -- right left lock");
}
}
}
});
t1.start();
t2.start();
}
I got asked this question recently in an interview.
Write a program with two threads (A and B), where A prints 1 , B prints 2 and so on until 50 is reached.
How do we go about doing that ?
The essence of the assignment is to demonstrate how a thread can signal another one. Most common way is to use blocking queues, but here a signal does not carry any information, so a Semaphore is sufficient.
Create thread class which is parameterized with 2 Semaphores: input and output:
class ThreadPrinter implements Runnable {
int counter;
Semaphore ins, outs;
ThreadPrinter(int counter, Semaphore ins, Semaphore outs) {
this.counter = counter;
this.ins = ins;
this.outs = outs;
}
#Override
public void run() {
for (int i = 0; i < 25; i++) {
ins.aquire(); // wait for permission to run
System.out.println("" + counter);
outs.release(); // allow another thread to run
counter += 2;
}
}
Create 2 Semaphores and pass them to 2 threads:
Semaphore a = new Semaphore(1); // first thread is allowed to run immediately
Semaphore b = new Semaphore(0); // second thread has to wait
ThreadPrinter tp1 = new ThreadPrinter(1, a, b);
ThreadPrinter tp2 = new ThreadPrinter(2, b, a);
Note semaphores a and b are passed in different order.
public class Test {
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 25; i++) {
synchronized (CommonUtil.mLock) {
incrementCount();
CommonUtil.mLock.notify();
try {
CommonUtil.mLock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 25; i++) {
synchronized (CommonUtil.mLock) {
incrementCount();
CommonUtil.mLock.notify();
try {
CommonUtil.mLock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
t1.start();
Thread.sleep(400);
t2.start();
t1.join();
t2.join();
}
private static void incrementCount() {
count++;
System.out.println("Count: " + count + " icnremented by: " + Thread.currentThread().getName());
}
}
class CommonUtil {
static final Object mLock = new Object();
}
I encountered the same problem and was expected to use only basics so I choose wait notify on shared object between threads
public class Message implements Runnable {
private static final int N = 10;
private Thread thread;
private static Object object = new Object();
public Message(String name){
thread = new Thread(this, name);
thread.start();
}
public void run(){
for(int i=0; i<N; i++){
synchronized (object) {
System.out.println(i + "--" + thread.getName());
object.notify();
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
In main method :
Message message1 = new Message("Ping");
Message message2 = new Message("Pong");
public class ThreadCounter implements Runnable {
private static int count = 0;
private Thread t;
public ThreadCounter(String tName){
t= new Thread(this, tName);
t.start();
}
#Override
public void run() {
for(int i=1; i<=5; i++){
synchronized (CommonUtil.mLock) {
incrementCount(t.getName());
CommonUtil.mLock.notify();
try {
CommonUtil.mLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void incrementCount(String tName){
System.out.println(tName+": "+(++ThreadCounter.count));
}
public static void main(String[] args) throws InterruptedException {
new ThreadCounter("Thread1");
Thread.sleep(500);
new ThreadCounter("Thread2");
}
}
class CommonUtil{
public static Object mLock = new Object();
}
hi please find answer here...pattern ABABABAB
package com.abhi.ThreadPractice;
public class Test {
public static void main(String[] args) throws InterruptedException {
final Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
// count++;
System.out.println("A");
try {
lock.wait();
lock.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
lock.notify();
//count++;
System.out.println("B");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
This is another solution:
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (lock) {
for (int i = 1; i <= 50; i += 2) {
System.out.println("T1=" + i);
t1turn = false;
try {
lock.notifyAll();
lock.wait();
} catch (InterruptedException e) {
}
}
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (lock) {
for (int i = 2; i <= 50; i += 2) {
if (t1turn)
try {
lock.wait();
} catch (InterruptedException e) {
}
System.out.println("T2=" + i);
t1turn = true;
lock.notify();
}
}
}
});
t1.start();
t2.start();
May be this is still relevant:
public class MyRunnable implements Runnable {
public static int counter = 0;
public static int turn = 0;
public static Object lock = new Object();
#Override
public void run() {
while (counter < 50) {
synchronized (lock) {
if (turn == 0) {
System.out.println(counter + " from thread "
+ Thread.currentThread().getName());
turn = 1;
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
} else {
turn = 0;
lock.notify();
}
}
}
}
}
and then the main function
public static void main(String[] args) {
Thread threadA = new Thread(new MyRunnable());
Thread threadB = new Thread(new MyRunnable ());
threadA.start();
threadB.start();
}
public class PingPong extends Thread {
static StringBuilder object = new StringBuilder("");
public static void main(String[] args) throws InterruptedException {
Thread t1 = new PingPong();
Thread t2 = new PingPong();
t1.setName("\nping");
t2.setName(" pong");
t1.start();
t2.start();
}
#Override
public void run() {
working();
}
void working() {
while (true) {
synchronized (object) {
try {
System.out.print(Thread.currentThread().getName());
object.notify();
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
This was the simplest solution, I was able to think of. It uses a synchronized method and uses the notify() and the wait() to alternatively print the numbers. Hope it helps. :)
public class program implements Runnable
{
static int count =1;
private static final int MAX_COUNT = 50;
public synchronized void print ()
{
System.out.println(Thread.currentThread().getName() + " is printing " + count);
count++;
notify();
try{
if(count>MAX_COUNT)
return;
wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
public void run()
{
for(int i=0;i<MAX_COUNT/2;i++)
{
print();
}
}
public static void main(String[] args) {
program x= new program();
Thread t0= new Thread(x);
Thread t1= new Thread(x);
t0.start();
try
{
Thread.sleep(1);
} catch (InterruptedException e){
e.printStackTrace();
}
t1.start();
}
}
//simply use wait and notify and and set a counter and it will do
public class ThreadalternatePrint implements Runnable {
static int counter =0;
#Override
public synchronized void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(counter<51)
{ ++counter;
notify();
System.out.println(Thread.currentThread().getName());
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ThreadalternatePrint obj1 = new ThreadalternatePrint();
Thread Th1 = new Thread(obj1);
Thread Th2 = new Thread(obj1);
Th1.setName("Thread1");
Th2.setName("Thread2");
Th1.start();
Th2.start();
}
}
public class Testing implements Runnable {
private static int counter = 1;
private static final Object lock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new Testing(), "1");
t1.start();
Thread t2 = new Thread(new Testing(), "2");
t2.start();
}
#Override
public void run() {
while (counter<=100) {
synchronized (lock) {
if (counter % 2 == 0) {
System.out.println(counter +" Written By Thread-"+ Thread.currentThread().getName());
counter++;
try {
lock.notifyAll();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (counter % 2 == 1) {
System.out.println(counter +" Written By Thread-"+ Thread.currentThread().getName());
counter++;
try {
lock.notifyAll();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
I have created a pretty basic Solution for it using the Reentrant Lock.
package com.multithreding.trylock;
import java.util.concurrent.locks.ReentrantLock;
public class TryLock extends Thread {
static int intitialCount = 50; //Value till which you want to print
int valueToSubtract = 0; //Value by which difference you want to print the series like 1,2,3
static ReentrantLock alternate = new ReentrantLock();
public TryLock(String name) {
this.setName(name);
}
public void run() {
while (intitialCount > 1) {
if (valueToSubtract > 0) {
alternate.lock();
intitialCount = intitialCount - valueToSubtract;
valueToSubtract = 0;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("value Subtracted " + intitialCount + " by the Thread" + this.getName());
alternate.unlock();
} else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
valueToSubtract++;
}
}
}
}
package com.multithreding.trylock;
public class AlternatePrint {
public static void main(String[] args) throws InterruptedException{
//You can add as many thread to print then in different number of series
TryLock t1 = new TryLock("Odd One");
TryLock t2 = new TryLock("Even Value");
t1.start();
t2.start();
}
}
This solution is modular as well,
You can add 'n' number of Threads to print the alternate series. i.e Using 3 thread at once
You can also print the series with more than Difference of more than 1. i.e 1,3,5 etc
package thread;
public class Pingpong extends Thread {
static StringBuilder object = new StringBuilder("");
static int i=1;
#Override
public void run() {
working();
}
void working() {
while (i<=10) {
synchronized (object) {
try {
System.out.println(Thread.currentThread().getName() +" "+ i);
i++;
object.notify();
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Pingpong();
Thread t2 = new Pingpong();
t1.setName("Thread1");
t2.setName("Thread2");
t1.start();
t2.start();
}
}
Thread1 1
Thread2 2
Thread1 3
Thread2 4
Thread1 5
Thread2 6
Thread1 7
Thread2 8
Thread1 9
Thread2 10
This answer is generic i.e. not only to print numbers alternately from 2 threads but to execute 2 threads alternately.
The above approaches are commendable but this one doesn't need any lock but instead it uses an AtomicInteger variable alongwith 2 AtomicBooleans to indicate when one thread has finished executing so that the other can finish executing the rest of its remaining execution.
This will work in all 3 cases:
When number of executions of both threads are same.
When first thread finishes before second thread and second thread has more number of executions than first thread.
When second thread finishes before first thread and first thread has more number of executions than second thread.
public class TestAlternateExecutionOfTwoThreads
{
private static final AtomicInteger count = new AtomicInteger(0);
private static final AtomicBoolean firstIsDone = new AtomicBoolean(false);
private static final AtomicBoolean secondIsDone = new AtomicBoolean(false);
// change the below values to change the number of iterations each thread should
// run. In this example, the initial value are hard-coded but you can change
// them as well.
private static final int finalOfFirstThread = 10;
private static final int finalOfSecondThread = 109;
public static void main(String[] args)
{
Runnable r1 = () -> {
int i = 1;
for(; i <= finalOfFirstThread; )
{
while(count.get() == 0)
{
System.out.println(i);
count.incrementAndGet();
i++;
}
if(count.get() == 1 && secondIsDone.get() && i != (finalOfFirstThread + 1))
{
System.out.println(i);
i++;
}
}
firstIsDone.set(true);
};
Runnable r2 = () -> {
int j = 100;
for (; j <= finalOfSecondThread; )
{
while(count.get() == 1)
{
System.out.println(j);
count.decrementAndGet();
j++;
}
if(count.get() == 0 && firstIsDone.get() && j != (finalOfSecondThread + 1))
{
System.out.println(j);
j++;
}
}
secondIsDone.set(true);
};
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
I guess this might help.
Although it is not standard but i hope it provides a simpler approach.
public class ThreadDemo
{
public static void main (String [] args)
{
PrintDemo pd=new PrintDemo();
MyThread1 mt1 = new MyThread1 ("T1",pd);
MyThread2 mt2 = new MyThread2 ("T2",pd);
mt1.start ();
mt2.start();
}
}
class PrintDemo {
private boolean oddFlag=true;
public synchronized void printOdd(int i,String tName){
if(oddFlag==false){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println("\nThread "+tName+" count:"+i);
oddFlag=false;
notify();
}
}
public synchronized void printEven(int i,String tName){
if(oddFlag==true){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println("\nThread "+tName+" count:"+i);
oddFlag=true;
notify();
}
}
}
class MyThread1 extends Thread
{
private PrintDemo pd;
private String name;
MyThread1(String threadName,PrintDemo pd){
this.name=threadName;
this.pd=pd;
}
public void run ()
{
for(int i=1;i<=50;i+=2){
pd.printOdd(i,name);
}
}
}
class MyThread2 extends Thread
{
private PrintDemo pd;
private String name;
MyThread2(String threadName,PrintDemo pd){
this.name=threadName;
this.pd=pd;
}
public void run ()
{
for(int i=2;i<=50;i+=2){
pd.printEven(i,name);
}
}
}
If i know a specific thread id. How to do the following?
Thread.getThreadById(id).continueWork();
Is it possible?
public class Test implements Runnable {
public void run() {
while(true){
pause();
doSomework();
}
}
private void doSomework() {
System.out.println("do some work");
}
public synchronized void pause() {
if (Tester.waitCondition == true) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void continueWork() {
notify();
}
}
public class Tester {
public static boolean waitCondition = true;
public static void main(String[] args) {
Thread nThread = new Thread(new Test());
nThread.start();
waitCondition = false;
Thread nThread1 = new Thread(new Test());
nThread1.start();
Thread nThread2 = new Thread(new Test());
nThread2.start();
Thread nThread3 = new Thread(new Test());
nThread3.start();
Long id = nThread.getId();
Thread.getThreadById(id).continueWork();
}
}
You need block the thread with a lock , then call the lock's notify method to set blocked thread runnable .
If more than one thread to be continued , you will need Condition .
Like blow:
final Lock lock = new ReentrantLock();
final Condition condition1 = lock.newCondition();
final Condition condition2 = lock.newCondition();
Thread t = new Thread() {
#Override
public void run() {
try {
lock.lock();
condition1.await();
System.out.println("end cdt1");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
t.start();
Thread t1 = new Thread() {
#Override
public void run() {
try {
lock.lock();
condition2.await();
System.out.println("end cdt2");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
t1.start();
Thread.sleep(1000);
Thread tt = new Thread() {
#Override
public void run() {
try {
lock.lock();
condition1.signal();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
tt.start();
Thread.sleep(2000);
Thread tt1 = new Thread() {
#Override
public void run() {
try {
lock.lock();
condition2.signal();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
tt1.start();
Elaborating:
public class Tester {
// Apologies, I'm too lazy to create two separate files
static public class Test implements Runnable {
private void doSomework() {
System.out.print(
"do some work on Thread: "
+Thread.currentThread().getId()
);
try {
Thread.sleep(500); // just to simulate a load
}
catch(InterruptedException e) {
// ignore
}
}
public void run() {
do {
boolean shouldIWait=true;
synchronized(Tester.lockingObj) {
Boolean flag=Tester.waitConditions.get(Thread.currentThread().getId());
if(null!=flag) {
shouldIWait=flag.booleanValue();
} // if null, the tester started me before creating my flag. I'll wait
if(shouldIWait) {
// I need to wait for someone to wake me
try {
Tester.lockingObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
// well, I'm interrupted, so I'll do no more work.
break;
}
}
}
if(false==shouldIWait) {
// waiting no more
this.doSomework();
}
} while(true);
}
}
public static Object lockingObj=new Object();
public static TreeMap<Long, Boolean> waitConditions=
new TreeMap<Long, Boolean>();
public static void main(String[] args) {
Thread nThread = new Thread(new Test());
Thread nThread1 = new Thread(new Test());
Thread nThread2 = new Thread(new Test());
Thread nThread3 = new Thread(new Test());
// when starting, all threads will be waiting
waitConditions.put(nThread.getId(), true);
waitConditions.put(nThread.getId(), true);
waitConditions.put(nThread.getId(), true);
waitConditions.put(nThread.getId(), true);
nThread2.start();
nThread1.start();
nThread.start();
nThread3.start();
Long id = nThread.getId();
synchronized (lockingObj) { // when notified, all thread should wakeup
waitConditions.put(id, false); // but only nThread will be allowed to doSomeWork
lockingObj.notifyAll(); // wake up all the threads.
// Those not allowed, will go into
// back waiting
}
try {
// just to have the main thread still running for a while
Thread.sleep(3000);
} catch (InterruptedException e) {
}
// maybe we want to switch of nThread and start another?
synchronized (lockingObj) {
waitConditions.put(id, true);
waitConditions.put(nThread1.getId(), false);
lockingObj.notifyAll();
}
try {
// just to have the main thread still running for a while
Thread.sleep(3000);
} catch (InterruptedException e) {
}
}
}
I am trying to write a program with two Java threads. One shall print odd and the other shall print even numbers. The output should be in sequence. My code is not working properly. Please correct it and tell me what was the error.
public class App {
public static void main(String[] args) {
ThrdO to=new ThrdO();
Thread t1=new Thread(to);
ThredE te=new ThredE();
Thread t2=new Thread(te);
t1.start();
t2.start();
}
}
public class ThrdO implements Runnable{
PrintCl pcl =new PrintCl();
#Override
public void run() {
for(int i=0;i<10;i+=2)
pcl.Even(i);
}
}
public class ThredE implements Runnable {
PrintCl pcl =new PrintCl();
#Override
public void run() {
for(int i=1;i<10;i+=2)
try {
pcl.odd(i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public class PrintCl {
public void Even(int n) {
synchronized (this) {
System.out.println(n);
this.notifyAll();
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void odd(int n) throws InterruptedException {
synchronized (this) {
System.out.println(n);
this.notifyAll();
this.wait();
}
}
}
getting output
0 ,1
This is a much cleaner way of achieving what you want, without ugly sleeps in the code, not to mention that it will run faster than code with a sleep in it, for obvious reasons.
public class App {
public static void main(String[] args) {
PrintCl pcl = new PrintCl();
Thread t1 = new Thread(new ThrdEven(pcl));
Thread t2 = new Thread(new ThrdOdd(pcl));
t1.start();
t2.start();
}
}
public class ThrdEven implements Runnable {
private PrintCl pcl = null;
public ThrdEven(PrintCl pcl) {
this.pcl = pcl;
}
#Override
public void run() {
for (int i = 0; i < 10; i += 2) {
pcl.Even(i);
}
}
}
public class ThrdOdd implements Runnable {
private PrintCl pcl = null;
public ThrdOdd(PrintCl pcl) {
this.pcl = pcl;
}
#Override
public void run() {
for (int i = 1; i < 10; i += 2) {
pcl.odd(i);
}
}
}
public class PrintCl {
private final Object _lock = new Object();
private boolean isEvenAllowed = true;
public void Even(int n) {
synchronized (this._lock) {
while (!this.isEvenAllowed) {
try {
this._lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
System.out.println(n);
this.isEvenAllowed = false;
this._lock.notifyAll();
}
}
public void odd(int n) {
synchronized (this._lock) {
while (this.isEvenAllowed) {
try {
this._lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
System.out.println(n);
this.isEvenAllowed = true;
this._lock.notifyAll();
}
}
}
Please try following changes in your code:
public class App {
public static void main(String[] args) throws InterruptedException {
PrintCl pcl =new PrintCl();
ThrdO to=new ThrdO();
to.setPcl(pcl);
Thread t1=new Thread(to);
ThredE te=new ThredE();
te.setPcl(pcl);
Thread t2=new Thread(te);
t1.start();
Thread.sleep(1000);
t2.start();
}
}
And for Thrd0:
public class ThrdO implements Runnable {
PrintCl pcl =null;
#Override
public void run() {
for(int i=0;i<10;i+=2)
pcl.Even(i);
}
public PrintCl getPcl() {
return pcl;
}
public void setPcl(PrintCl pcl) {
this.pcl = pcl;
}
}
ThredE:
public class ThredE implements Runnable {
PrintCl pcl =null;
#Override
public void run() {
for(int i=1;i<10;i+=2)
try {
pcl.odd(i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public PrintCl getPcl() {
return pcl;
}
public void setPcl(PrintCl pcl) {
this.pcl = pcl;
}
}
Your code has two basic problems
Every thread have its own printing resource . Hence once printing their first number they are waiting for notification endlessly.
Once you will fix this issue , Another issue is your one thread will be finished but second thread would still be waiting for its notification and it will never die.
I have fixed both issues in below code
public class Test {
public static void main(String[] args) throws InterruptedException {
PrintCl pcl =new PrintCl();
ThrdO to=new ThrdO(pcl);
Thread t1=new Thread(to);
ThredE te=new ThredE(pcl);
Thread t2=new Thread(te);
t1.start();
Thread.sleep(1000);// just to ensure that T1 should start first
t2.start();
}
}
class ThrdO implements Runnable{
private PrintCl pcl;
public ThrdO(PrintCl pcl) {
this.pcl = pcl;
}
#Override
public void run() {
for(int i=0;i<10;i+=2) {
try {
pcl.Even(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (pcl){
System.out.println("Releasing lock on pcl");
pcl.notify();
}
System.out.println("ThrdO has finished its working");
}
}
class ThredE implements Runnable {
PrintCl pcl ;
public ThredE(PrintCl pcl) {
this.pcl = pcl;
}
#Override
public void run() {
for (int i = 1; i < 10; i += 2) {
try {
pcl.odd(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (pcl){
System.out.println("Releasing lock on pcl ");
pcl.notify();
}
System.out.println("ThredE has finished its working");
}
}
class PrintCl {
public void Even(int n) throws InterruptedException {
synchronized (this) {
System.out.println("even - "+n);
this.notifyAll();
this.wait();
}
}
public void odd(int n) throws InterruptedException {
synchronized (this) {
System.out.println("odd "+n);
this.notifyAll();
this.wait();
}
}
}
How to write a simple fair lock analog to new ReentrantLock(true)?
public class Main1 {
public static void main(String[] args) {
// Lock lock = new ReentrantLock(true);
CustomLock lock = new CustomLock();
new Thread(new Producer(lock)).start();
new Thread(new Consumer(lock)).start();
}
}
class Producer implements Runnable {
private Lock lock;
private CustomLock customLock;
public Producer(Lock lock) {
this.lock = lock;
}
public Producer(CustomLock lock) {
this.customLock = lock;
}
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// lock.lock();
customLock.lock();
System.out.println("Producer before");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Producer after");
// lock.unlock();
customLock.unlock();
}
}
}
class Consumer implements Runnable {
private Lock lock;
private CustomLock customLock;
public Consumer(Lock lock) {
this.lock = lock;
}
public Consumer(CustomLock lock) {
this.customLock = lock;
}
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// lock.lock();
customLock.lock();
System.out.println("Consumer before");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer after");
// lock.unlock();
customLock.unlock();
}
}
}
class CustomLock{
private boolean isLocked;
public synchronized void lock(){
while (isLocked) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLocked = true;
}
public synchronized void unlock(){
if(isLocked){
isLocked = false;
notify();
}
}
}
Custom not fair Lock (I am not sure that it's correct)
class CustomLock{
private boolean isLocked;
public synchronized void lock(){
while (isLocked) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLocked = true;
}
public synchronized void unlock(){
if(isLocked){
isLocked = false;
notify();
}
}
}
If you want a fair lock you need to use a list and notify threads following the list order.