I wrote a small program to print odd-even numbers alternatively but have a question:
Since thread should wait at await call so how is reentrant lock is getting unlocked?
public class Worker implements Runnable
{
private ReentrantLock rLock = null;
private Condition condition = null;
private String name;
volatile static boolean isEvenTurn = true;
public Worker(String name, ReentrantLock rLock, Condition condition)
{
this.name = name;
this.rLock = rLock;
this.condition = condition;
}
#Override
public void run()
{
try
{
if(name.equals("ODD"))
printOdd();
else
printEven();
}
catch(Exception e) { e.printStackTrace();}
}
private void printOdd() throws Exception
{
while(isEvenTurn);
for(int i=1;i<10;i+=2)
{
try
{
rLock.lock();
System.out.println(i);
}
catch(Exception e) {e.printStackTrace();}
finally
{
condition.signal();
condition.await();
rLock.unlock();
}
}
}
private void printEven() throws Exception
{
for(int i=0;i<10;i+=2)
{
try
{
rLock.lock();
System.out.println(i);
isEvenTurn = false;
}
catch(Exception e) {e.printStackTrace();}
finally
{
condition.signal();
condition.await();
rLock.unlock();
}
}
}
public static void main(String[] args)
{
ReentrantLock rLock = new ReentrantLock();
ExecutorService service = Executors.newFixedThreadPool(2);
Condition c = rLock.newCondition();
Worker oddPrinter = new Worker("ODD",rLock,c);
Worker evenPrinter = new Worker("EVEN",rLock,c);
service.execute(evenPrinter);
service.execute(oddPrinter);
service.shutdown();
}
}
In printEven() method add this line: in finally block:
finally
{
condition.signal();
if(i < 10)condition.await();
rLock.unlock();
}
By adding this condition, when your
i = 10 your thread will not wait anymore.
Related
new to multithreading. I wrote this program which should be a solution to the producer-consumer problem. The problem is that both a producer and a consumer end up in the waiting state. What seems to be wrong? (And everything else what is wrong ^_^) Thanks in advance.
Main class:
package producer.consumer2;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Buffer<Integer> bf = new Buffer<>(10);
Producer prod = new Producer(bf);
Consumer cons = new Consumer(bf);
prod.setConsumer(cons);
cons.setProducer(prod);
new Thread(prod).start();
new Thread(cons).start();
if(quitInput()) {
prod.terminate();
cons.terminate();
}
}
private static boolean quitInput() {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
do {
if(line.toLowerCase().equals("q") || line.toLowerCase().equals("quit")) {
sc.close();
return true;
}
line = sc.nextLine();
} while(true);
}
}
Buffer class:
package producer.consumer2;
import java.util.ArrayList;
public class Buffer<E> {
private final int MAX_LENGTH;
private ArrayList<E> values;
public Buffer(int length){
MAX_LENGTH = length;
values = new ArrayList<E>(length);
}
public synchronized void add(E e) {
if(values.size() < MAX_LENGTH) {
values.add(e);
System.out.println(values);
} else {
throw new RuntimeException("Buffer is full at the moment.");
}
}
public synchronized boolean isEmpty() {
return values.size() == 0;
}
public synchronized boolean isFull() {
return values.size() >= MAX_LENGTH ? true : false;
}
public synchronized E remove(int index) {
E val = values.remove(index);
System.out.println(values);
return val;
}
}
Consumer class:
package producer.consumer2;
public class Consumer implements Runnable {
private final Buffer<Integer> bf;
private volatile boolean running = true;
private Producer prod;
public Consumer(Buffer<Integer> bf) {
this.bf = bf;
}
public void setProducer(Producer prod) {
this.prod = prod;
}
#Override
public void run() {
int sum = 0;
int counter = 0;
while (running) {
if (bf.isEmpty()) {
if (prod != null) {
synchronized (prod) {
prod.notify();
}
}
myWait(0);
} else {
sum += bf.remove(0);
counter++;
}
}
System.out.println("for first " + counter + " nums an avg = " + ((double) sum / counter));
}
private void myWait(long millisecs) {
System.out.println("consumer is waiting.");
try {
synchronized (this) {
this.wait(millisecs);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("consumer is NOT waiting.");
}
public void terminate() {
this.running = false;
}
}
Producer class:
package producer.consumer2;
public class Producer implements Runnable {
private final Buffer<Integer> bf;
private volatile boolean running = true;
private Consumer cons;
public Producer(Buffer<Integer> bf) {
this.bf = bf;
}
public void setConsumer(Consumer cons) {
this.cons = cons;
}
#Override
public void run() {
int counter = 1;
while (running) {
if (bf.isFull()) {
if (cons != null) {
synchronized (cons) {
cons.notify();
}
}
myWait(0);
} else {
bf.add(counter);
counter++;
}
}
}
private void myWait(long millisecs) {
System.out.println("producer is waiting.");
try {
synchronized (this) {
this.wait(millisecs);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("producer is NOT waiting.");
}
public void terminate() {
this.running = false;
}
}
Looks like a regular case of 'missed signal'. Since both consumer and producer just wait without checking a condition, yu have no way to ensure the notify actually happens during the waiting.
e.g. in Consumer :
if (prod != null) {
synchronized (prod) {
prod.notify();
}
}
myWait(0);
Note that if, after prod.notify() the Production thread does all of its work, and notifies the consumer, before it even starts waiting, the consumer will start waiting for a signal that's already been given, and missed.
Always take into account that waiting may not be needed anymore. So always check a condition before even starting to wait. In your case here, the consumer should not even begin waiting if the buffer is full. And likewise the producer should not start waiting if the buffer is empty.
It's also possible to get spurious wake ups. So you'll have to re-check the condition when returning from waiting. The typical idiom is this :
synchronized(monitor) {
while (!stateBasedCondition) {
monitor.wait();
}
}
I have a ConsumerProducer object on which I want to acquire lock from two different threads. The class is as below:
public class ConsumerProducer {
public String stringPool = null;
public void put(String s){
stringPool = s;
}
public String get(){
String ret = stringPool;
stringPool = null;
return ret;
}
}
The thread impl class is as below:
public class WaitNotifyTest implements Runnable {
private String threadType;
public ConsumerProducer cp;
public static volatile int i = 1;
public WaitNotifyTest(String threadType, ConsumerProducer cp) {
this.threadType = threadType;
this.cp = cp;
}
public static void main(String[] args) throws InterruptedException {
ConsumerProducer cp = new ConsumerProducer();
WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);
Thread t1 = new Thread(test1);
Thread t2 = new Thread(test2);
t1.start();
t2.start();
t1.join();
t2.join();
}
#Override
public void run() {
while (true) {
if (threadType.equalsIgnoreCase("Consumer")) {
synchronized (cp) {
try {
if (null != cp.get()) {
cp.wait();
}
consume();
System.out.println("notify from Consumer");
cp.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
synchronized (cp) {
try {
if (null == cp.get()) {
cp.wait();
}
produce();
System.out.println("notify from Producer");
cp.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (i == 5) {
break;
}
i++;
}
}
public void consume() {
System.out.println("Putting: Counter" + i);
cp.put("Counter" + i);
}
public void produce() {
System.out.println("getting: " + cp.get());
}
}
But when I run the code it is facing some kind of deadlock and it is stuck printing like
Putting: Counter3
notify from Consumer
Something is going terribly wrong but I am not able to identify. Please help.
Your consumer is doing producer's job and producer is doing consumer's job.
Exchange their responsibility and modify the condition to wait. Please refer to the code below.
Consumer will wait when there is nothing to get and he will release the lock of cp. So that producer has chance to go into the synchronized block.
Producer only produces when there is nothing or he will wait. After that, he will release the lock of cp. So that consumer has chance to go into the synchronized block.
Consumer is who get things away.
Producer is who put things to table.
According to your comment. You want to put Counter from 1 to 5, so you should add i++ only in Producer thread. How can you control its increase in both threads?
You don't judge whether it's consumer or producer calling the get() from cp object but assign null to stringPool. It's obvious wrong and will make consumer get null from public space. I add a new method clearString() which will set public space to null only when consumer has comsumed the product.
public class WaitNotifyTest implements Runnable {
private String threadType;
public ConsumerProducer cp;
public static volatile int i = 0;
public WaitNotifyTest(String threadType, ConsumerProducer cp) {
this.threadType = threadType;
this.cp = cp;
}
public static void main(String[] args) throws InterruptedException {
ConsumerProducer cp = new ConsumerProducer();
WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);
Thread t1 = new Thread(test1);
Thread t2 = new Thread(test2);
t1.start();
t2.start();
t1.join();
t2.join();
}
#Override
public void run() {
while (true) {
if (threadType.equalsIgnoreCase("Consumer")) {
synchronized (cp) {
try {
/*
* Consumer will wait when there is nothing to get and he will release the lock of cp.
* So that producer has change to go into the synchronized block.
*/
if (null == cp.get()) {
cp.wait();
}
consume();
System.out.println("notify from Consumer");
cp.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
synchronized (cp) {
try {
/*
* Producer only produce when there is nothing or he will wait. At the same time, he will release the lock of cp.
* So that consumer has chance to go into the synchronized block.
*/
if (null != cp.get()) {
cp.wait();
}
i++;
produce();
System.out.println("notify from Producer");
cp.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (i == 5) {
break;
}
}
}
public void consume() {
System.out.println("getting: " + cp.get());
cp.clearString();
}
public void produce() {
System.out.println("Putting: Counter" + i);
cp.put("Counter" + i);
}}
Also see the ConsumerProducer class.
public class ConsumerProducer {
public String stringPool = null;
public void put(String s){
stringPool = s;
}
public String get(){
return stringPool;
}
public void clearString(){
stringPool = null;
}
}
Updated code is here:
ConsumerProducer.java:
public class ConsumerProducer {
public volatile String stringPool = null;
public void put(String s){
this.stringPool = s;
}
public String get(){
String ret = this.stringPool;
//this.stringPool = null;
return ret;
}
//added
public void clearString(){
this.stringPool = null;
}
}
WaitNotifyTest.java
public class WaitNotifyTest implements Runnable {
private String threadType;
public ConsumerProducer cp;
public static volatile int i = 0;
public WaitNotifyTest(String threadType, ConsumerProducer cp) {
this.threadType = threadType;
this.cp = cp;
}
public static void main(String[] args) throws InterruptedException {
ConsumerProducer cp = new ConsumerProducer();
WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);
Thread t1 = new Thread(test1);
Thread t2 = new Thread(test2);
t1.start();
t2.start();
t1.join();
t2.join();
}
#Override
public void run() {
while (true) {
if (threadType.equalsIgnoreCase("Consumer")) {
synchronized (cp) {
try {
if (null == cp.get()) {
cp.wait();
}
consume();
System.out.println("notify from Consumer");
cp.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
synchronized (cp) {
try {
if (null != cp.get()) {
cp.wait();
}
i++;
produce();
System.out.println("notify from Producer");
cp.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (i == 5) {
break;
}
}
}
public void produce() {
System.out.println("Putting: Counter" + i);
cp.put("Counter" + i);
}
public void consume() {
System.out.println("getting: " + cp.get());
cp.clearString();
}
}
I have created two runnable jobs: PrintEvenNumbersJob and PrintOddNumbersJob and spawned two threads to execute these jobs. This seems to work perfectly fine! But I smell something suspicious about this implementation. Can I have some comments and advice on this implementation?
The problem that I see with this implementation is that the program terminates only when thread1 gains the lock to the object lock first otherwise it print the odd first even second order and doesn't terminate unless I supply yet another statement "lock.notify" after for statement in PrintEvenNumbersJob (as in this implementation). My question here is how to make sure that thread1 is executed first.
public class PrintEvenNumbersJob implements Runnable {
private Object lock;
public PrintEvenNumbersJob(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 0; i <= 10; i += 2) {
lock.notify();
System.out.println(i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify(); // not required if thread1 gains lock first
}
}
}
public class PrintOddNumbersJob implements Runnable {
private Object lock;
public PrintOddNumbersJob(Object lock) {
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
for (int i = 1; i < 10; i += 2) {
lock.notify();
System.out.println(i);
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify();
}
}
}
public class EvenOddManager {
public static void main(String[] args) {
Object lock = new Object();
PrintEvenNumbersJob printEvenNumbersJob = new PrintEvenNumbersJob(lock);
PrintOddNumbersJob printOddNumbersJob = new PrintOddNumbersJob(lock);
Thread thread1 = new Thread(printEvenNumbersJob);
Thread thread2 = new Thread(printOddNumbersJob);
thread2.start();
thread1.start();
}
}
Have you try using Semaphores? It's easier because you don't need to worry about the order that wait and notify are called (if you call notify before the wait, it's "lost")
Sample code:
import java.util.concurrent.*;
public class Test {
private final Semaphore oddJobPermits = new Semaphore(0);
private final Semaphore evenJobPermits = new Semaphore(1);
private class EvenJob implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
try {
evenJobPermits.acquire();
System.out.println(i * 2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
oddJobPermits.release();
}
}
}
}
private class OddJob implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
try {
oddJobPermits.acquire();
System.out.println(i * 2 + 1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
evenJobPermits.release();
}
}
}
}
public void run() {
new Thread(new EvenJob()).start();
new Thread(new OddJob()).start();
}
public static void main(String[] args) {
new Test().run();
}
}
I believe you will need a referee:
public class Referee {
private boolean evensTurn = true;
public void waitMyTurn(boolean even) {
synchronized(this) {
while (even != evensTurn) {
try {
wait();
} finally {
}
}
}
}
public void done() {
synchronized(this) {
evensTurn = !evensTurn;
notify();
}
}
}
public class PrintEvenNumbersJob implements Runnable {
private Referee referee;
public PrintEvenNumbersJob(Referee referee) {
this.referee = referee;
}
#Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
referee.waitMyTurn(true);
System.out.println(i);
referee.done();
}
}
}
public class PrintOddNumbersJob implements Runnable {
private Referee referee;
public PrintOddNumbersJob(Referee referee) {
this.referee = referee;
}
#Override
public void run() {
for (int i = 0; i <= 10; i += 2) {
referee.waitMyTurn(false);
System.out.println(i);
referee.done();
}
}
}
I tried and tested this code. It works using Semaphore
public class TestSemaphore
{
public static void main(String[] args)
throws Exception
{
AtomicInteger count = new AtomicInteger();
Semaphore s = new Semaphore(1, true);
Semaphore t = new Semaphore(1, true);
OddNumberThread oThread = new OddNumberThread(count, s, t);
EvenNumberThread eThread = new EvenNumberThread(count, s, t);
eThread.start();
oThread.start();
}
static class EvenNumberThread
extends Thread
{
private AtomicInteger count;
private Semaphore s, t;
public EvenNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
{
super("Even");
count = pCount;
s = pS;
t = pT;
}
#Override
public void run()
{
// Make this thread wait until even thread starts, Order will be incorrect if removed these lines.
s.acquireUninterruptibly();
while (count.intValue() <= 10)
{
try
{
// Double checking to make it work
s.acquireUninterruptibly();
System.out.println(getName() + " " + count.getAndIncrement());
}
finally
{
t.release();
}
}
}
}
static class OddNumberThread
extends Thread
{
private AtomicInteger count;
private Semaphore s, t;
public OddNumberThread(AtomicInteger pCount, Semaphore pS, Semaphore pT)
{
super("Odd");
count = pCount;
s = pS;
t = pT;
}
#Override
public void run()
{
// Start this thread first and start printing, Order will be incorrect if removed these lines.
t.acquireUninterruptibly();
s.release();
while (count.intValue() <= 10)
{
try
{
t.acquireUninterruptibly();
System.out.println(getName() + " " + count.getAndIncrement());
}
finally
{
s.release();
}
}
}
}
}
I'm trying to learn more about threads and thought that coming up with a solution to the producer/consumer problem would be a good start. One of the constraints I put on the solution was that the consumer does not know ahead of time how much the producer is producing. The code runs as expected and I've run it many many times, but that doesn't mean that it is free of flaws. Are there any problems with this solution?
package Multithreading.ProducerConsumer;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;
public class ProducerConsumer
{
private class Producer implements Runnable
{
#Override
public void run()
{
for(int i = 0; i < 1000; i++)
{
try
{
canProduce.acquire();
mutex.acquire();
queue.add(i);
mutex.release();
canConsume.release();
}
catch (InterruptedException ex)
{
;
}
}
try
{
canConsume.acquire();
isTryingToFinish = true;
canConsume.release();
}
catch (InterruptedException ex)
{
;
}
}
}
private class Consumer implements Runnable
{
#Override
public void run()
{
while(!isDone)
{
try
{
canConsume.acquire();
mutex.acquire();
System.out.println(queue.pop());
if(isTryingToFinish && queue.isEmpty())
{
isDone = true;
}
mutex.release();
canProduce.release();
}
catch (InterruptedException ex)
{
;
}
}
}
}
Semaphore canProduce;
Semaphore canConsume;
Semaphore mutex;
boolean isTryingToFinish = false;
boolean isDone = false;
final static int bufferSize = 100;
LinkedList<Integer> queue;
public ProducerConsumer()
{
queue = new LinkedList<>();
canProduce = new Semaphore(bufferSize);
canConsume = new Semaphore(0);
mutex = new Semaphore(1);
}
public void Go() throws InterruptedException
{
Thread p = new Thread(new Producer());
Thread c = new Thread(new Consumer());
p.start();
c.start();
p.join();
c.join();
System.out.println("Job Complete!");
}
public static void main(String[] args) throws InterruptedException
{
ProducerConsumer p = new ProducerConsumer();
p.Go();
}
}
You could look at MSDN's 'Example 2: Synchronizing two threads: a producer and a consumer'. It's c# but that should not be a problem.
I have a thread which does an action only when it gets exclusive access to 2 semaphores.
public void run(){
boolean a1=false;
boolean a2=false;
boolean a3=false;
while(true){
try{
if(res[1].tryAcquire()==true){
a1=true;
if((res[2].tryAcquire()==true){
a2=true;
if(res[3].tryAcquire()==true)){
a3=true;
System.out.println("Rolled the tobacco");
}
}
}
}
finally{
if(a1){
a1=false;
res[1].release();
}
if(a2){
a2=false;
res[2].release();
}
if(a3){
a3=false;
res[3].release();
}
}
}
}
}
Is there a better way to write this to make sure we do not upset the semaphore acquired count?
Is there a way to check if a semaphore is acquired by the current thread?
In Java 7 a try with Closeable is possible. There certainly must be nicer solutions.
public class Region implements Closeable {
private final Semaphore semaphore;
public Region(Semaphore semaphore) {
this.semaphore = semaphore;
if (!semaphore.tryAcquire()) {
throw NotAcquiredException(semaphore);
}
}
#Override
public void close() {
semaphore.release();
}
}
public class NotAcquiredException extends Exception { ... }
Usage:
public void run() {
boolean a1 = false;
boolean a2 = false;
boolean a3 = false;
while (true) {
try (Closeable r1 = new Region(res[1])) {
a1 = true;
try (Closeable r2 = new Region(res[2])) {
a2 = true;
try (Closeable r3 = new Region(res[3])) {
a3 = true;
System.out.println("Rolled the tobacco");
} catch (IOException e) {
}
} catch (IOException e) {
}
} catch (IOException e) {
}
}
You could separate each acquire into a try...finally, not shorter, but gets rid of some variables and makes it fairly obvious what should happen for each lock. (I changed the array to zero based)
public void run(){
while(true){
if(res[0].tryAcquire()){
try {
if(res[1].tryAcquire()) {
try {
if(res[2].tryAcquire()){
try {
System.out.println("Rolled the tobacco");
} finally {
res[3].release();
}
}
} finally {
res[2].release();
}
}
} finally{
res[1].release();
}
}
}
}
If you need to acquire a lot of locks or do this in several places, then maybe a helper class would be nice. At least hides the boilerplate code of acquire and releasing the semaphores.
public void run() {
SemaphoreHelper semaphoreHelper = new SemaphoreHelper(res);
while (true) {
try {
if (semaphoreHelper.aquireAll()) {
System.out.println("Rolled the tobacco");
}
} finally {
semaphoreHelper.releaseAquired();
}
}
}
private static class SemaphoreHelper {
private final Semaphore[] semaphores;
private int semaphoreIndex;
public SemaphoreHelper(Semaphore[] semaphores) {
this.semaphores = semaphores;
}
public void releaseAquired() {
while (semaphoreIndex > 0) {
semaphoreIndex--;
semaphores[semaphoreIndex].release();
}
}
public boolean aquireAll() {
while (semaphoreIndex < semaphores.length) {
if (!semaphores[semaphoreIndex].tryAcquire()) {
return false;
}
semaphoreIndex++;
}
return true;
}
}