Can't understand barrier code - java

I ran across this barrier code and I cannot understand the barrierPost method.
Im supposed to use this code to solve an exercise where two teams of threads race eachother to count to 10000.
I don't understand why the same condition has different results which are opposite
public class Barrier {
private int currentPosters = 0, totalPosters = 0;
private int passedWaiters = 0, totalWaiters = 1;
/**
* #param totalPosters - Nr of threads required to start the waiting threads
* #param totalWaiters - Nr of threads started later
*/
public Barrier (int totalPosters, int totalWaiters) {
this.totalPosters = totalPosters;
this.totalWaiters = totalWaiters;
}
public synchronized void init(int i) {
totalPosters = i; currentPosters=0;
}
public synchronized void barrierSet(int i) {
totalPosters = i; currentPosters=0;
}
public synchronized void barrierWait() {
boolean interrupted = false;
while (currentPosters = totalPosters) {
try {wait();}
catch (InterruptedException ie) {interrupted=true;}
}
passedWaiters++;
if (passedWaiters == totalWaiters) {
currentPosters = 0; passedWaiters = 0; notifyAll();
}
if (interrupted) Thread.currentThread().interrupt();
}
public synchronized void barrierPost() {
boolean interrupted = false; // In case a poster thread beats barrierWait, keep count of posters.
while (currentPosters == totalPosters) {
try {wait();}
catch (InterruptedException ie) {interrupted=true;}
}
currentPosters++;
if (currentPosters == totalPosters) notifyAll();
if (interrupted) Thread.currentThread().interrupt();
}
}
Can someone help?

Related

Producer-consumer problem - both end up waiting

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();
}
}

why is notify not getting called in my java code

Here's my code:
public class ProducerConsumer
{
public static void main(String[] args)
{
ProduceCosumeData p = new ProduceCosumeData();
ProducerT pt= new ProducerT(p); // with p obj i am creating thread
ConsumerT ct=new ConsumerT(p); // with same p obj i am creating thread
pt.start();
ct.start(); //i am starting 2 threads
}
}
class ProduceCosumeData
{
boolean flag;
public synchronized void printStringP(int n)
{
for(int i=0;i<n;i++)
{
try{
if(flag) //for frist time flag is flase so, wait will skip
wait();
else
flag=true; //for next time onwards wait() will get call
System.out.print("Pay");
notify();//after this why my wait() not canceling in inprintStringC()
}catch(Exception e)
{
System.out.print(e);
}
}
}
public synchronized void printStringC(int n)
{
for(int i=0;i<n;i++)
{
try{
wait(); // why it is not out of this after notify()
System.out.print("Tm");
notify();
}catch(Exception e)
{
System.out.print(e);
}
}
}
}
class ProducerT extends Thread
{
ProduceCosumeData p;
ProducerT(ProduceCosumeData p)
{
this.p=p; // i am saving the same obj for both threads
}
public void run()
{
p.printStringP(10); //it will print 10 times pay
}
}
class ConsumerT extends Thread
{
ProduceCosumeData p;
ConsumerT(ProduceCosumeData p)
{
this.p=p; // i am saving the same obj for both threads
}
public void run()
{
p.printStringC(10); //it will print 10 times tm
}
}
I am expecting the following output:
PayTm
PayTm
PayTm
... 10 times
but what I'm getting output is this:
Pay..
This is followed by a long wait.
The above two functions are in same object.
Why is the notify not releasing the wait() function? Even when I use notifyAll(), the output remains the same.
In you code, one of your threads is calling notify and the other is still not waiting. This produces a deadlock with both threads waiting.
You need to fix your use of the synchronization flag, don't call wait if it is not needed. Also, checking the locking condition is still available after the wait() is a good practice.
This is your ProduceConsumeData class with the use of the flag fixed:
class ProduceCosumeData
{
boolean flag;
public synchronized void printStringP(int n)
{
for(int i=0;i<n;i++)
{
try{
while (flag == true) {
wait();
}
flag=true;
System.out.print("Pay");
notify();
}catch(Exception e)
{
System.out.print(e);
}
}
}
public synchronized void printStringC(int n)
{
for(int i=0;i<n;i++)
{
try{
while(flag == false) {
wait();
}
System.out.print("Tm");
flag = false;
notify();
}catch(Exception e)
{
System.out.print(e);
}
}
}
}
You have used a general wait() with the synchronization in the method. Try using an object-synchronised version, such as synchronized(this){ wait(); } then whatever, to prevent cyclic dependencies of multiple threads on the same object, which is very very dangerous for any multithreaded program.
Or, more simply, implement a proper clone() method in your ProducerConsumerData class, and then to the 1st thread pass this object, and to the next pass its clone. Try using p.clone() instead of p in the second thread's constructor.
As answered above, you can make printStringP() 's notify() only get called when flag is true, not always.
This is the classic misconception that trips up almost everyone who tries to use wait and notify. Really they are so old and broken they shouldn't even be taught any more IMHO.
When printStringP calls notify() printStringC is not waiting yet.
class ProduceCosumeData {
// Variable shared between threads should be volatile.
volatile boolean flag;
public synchronized void printStringP(int n) {
for (int i = 0; i < n; i++) {
try {
//for frist time flag is flase so, wait will skip
if (flag) {
System.err.println("Waiting in printStringP");
wait();
} else {
System.err.println("flag now true");
flag = true; //for next time onwards wait() will get call
}
System.out.print("Pay");
System.err.println("printStringP notify");
notify();//after this why my wait() not canceling in inprintStringC()
} catch (Exception e) {
System.out.print(e);
}
}
}
public synchronized void printStringC(int n) {
for (int i = 0; i < n; i++) {
try {
System.err.println("Waiting in printStringC");
wait(); // why it is not out of this after notify()
System.out.print("Tm");
System.err.println("printStringC notify");
notify();
} catch (Exception e) {
System.out.print(e);
}
}
}
}
class ProducerT extends Thread {
ProduceCosumeData p;
ProducerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringP(10); //it will print 10 times pay
}
}
class ConsumerT extends Thread {
ProduceCosumeData p;
ConsumerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringC(10); //it will print 10 times tm
}
}
public void test() {
ProduceCosumeData p = new ProduceCosumeData();
ProducerT pt = new ProducerT(p); // with p obj i am creating thread
ConsumerT ct = new ConsumerT(p); // with same p obj i am creating thread
pt.start();
ct.start(); //i am starting 2 threads
}
prints
flag now true
PayprintStringP notify
Waiting in printStringP
Waiting in printStringC
To fix this don't use wait/notify it is broken for all but the very experienced. The same functionality can be achieved in a stable fashion using Locks and Conditions or almost any other java.util.concurrent class.
In the second iteration of printStringP the attribute flag is true and then the two threads are waiting.
Please find the below code snippet.
package com.java.examples;
public class ProducerConsumer {
public static void main(String[] args) throws InterruptedException {
ProduceCosumeData p = new ProduceCosumeData();
ProducerT pt = new ProducerT(p); // with p obj i am creating thread
ConsumerT ct = new ConsumerT(p); // with same p obj i am creating thread
pt.start();
Thread.sleep(1000);
ct.start(); // i am starting 2 threads
}
}
class ProduceCosumeData {
boolean flag = false;
public synchronized void printStringP(int n) {
for (int i = 0; i < n; i++) {
try {
if (flag) {
notify();
} else
flag = true;
System.out.println("Pay");
if (i <= n - 1) {
wait();
} else {
break;
}
} catch (Exception e) {
System.out.print(e);
}
}
notify();
}
public synchronized void printStringC(int n) {
for (int i = 0; i < n; i++) {
try {
if (flag) {
System.out.println("Tm");
if (i <= n - 1) {
notify();
} else {
break;
}
} else
flag = false;
wait();
} catch (Exception e) {
System.out.print(e);
}
}
}
}
class ProducerT extends Thread {
ProduceCosumeData p;
ProducerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringP(10); // it will print 10 times pay
}
}
class ConsumerT extends Thread {
ProduceCosumeData p;
ConsumerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringC(10); // it will print 10 times tm
}
}

Creating a Synchronized Buffer for Producer/Consumer pattern in Java

I implemented a buffer for the producer/consumer pattern, however, it seems that the Consumer never acquires the lock so Starvation occurs. I can't identify why this happens since both put() and take() seem to release the lock properly...
I know there is BlockingQueue and other nice implementations, but I want to implement this using wait() and notify() as an exercise.
public class ProducerConsumerRaw {
public static void main(String[] args) {
IntBuffer buffer = new IntBuffer(8);
ConsumerRaw consumer = new ConsumerRaw(buffer);
ProducerRaw producer = new ProducerRaw(buffer);
Thread t1 = new Thread(consumer);
Thread t2 = new Thread(producer);
t1.start();
t2.start();
}
}
class ConsumerRaw implements Runnable{
private final IntBuffer buffer;
public ConsumerRaw(IntBuffer b){
buffer = b;
}
public void run() {
while(!buffer.isEmpty()) {
int i = buffer.take();
System.out.println("Consumer reads "+i); // this print may not be in the order
}
}
}
class ProducerRaw implements Runnable{
private final IntBuffer buffer;
ProducerRaw(IntBuffer b) {
this.buffer = b;
}
public void run(){
for (int i = 0; i < 20; i++) {
int n = (int) (Math.random()*100);
buffer.put(n);
System.out.println("Producer puts "+n);
}
}
}
class IntBuffer{
private final int[] storage;
private volatile int end;
private volatile int start;
public IntBuffer(int size) {
this.storage = new int[size];
end = 0;
start = 0;
}
public void put(int n) { // puts add the END
synchronized(storage) {
boolean full = (start == (end+storage.length+1)%storage.length);
while(full){ // queue is full
try {
storage.notifyAll();
storage.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.storage[end] = n;
end = incrementMod(end);
storage.notifyAll();
}
}
public int take(){
synchronized(storage) {
while (end == start) { // empty queue
try {
storage.notifyAll(); // notify waiting producers
storage.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int index = start;
start = incrementMod(start);
storage.notifyAll(); // notify waiting producers
return this.storage[index];
}
}
private int incrementMod(int index) {
synchronized (storage) {
if (index == storage.length-1) return 0;
else return index+1;
}
}
public boolean isEmpty(){
synchronized (storage) {
return (start == end);
}
}
}
This is at least one problem, in your put method:
boolean full = (start == (end+storage.length+1)%storage.length);
while(full){ // queue is full
// Code that doesn't change full
}
If full is ever initialized as true, how do you expect the loop to end?
The other problem is this loop, in the consumer:
while(!buffer.isEmpty()) {
int i = buffer.take();
System.out.println("Consumer reads "+i);
}
You're assuming the producer never lets the buffer get empty - if the consumer starts before the producer, it will stop immediately.
Instead, you want some way of telling the buffer that you've stopped producing. The consumer should keep taking until the queue is empty and won't receive any more data.

Multithread - even odd sequence

I was attempting to solve a multi threaded problem and I am facing difficulties getting to know its behavior.
The problem is:
There are 2 threads which simultaneously consume even and odd numbers. I have to introduce the thread communication between them to have the "consumption" in natural ordering.
here is my code
public class EvenOddDemo {
public static void main(String[] args) {
Number n = new Number();
EvenThread et = new EvenThread(n);
OddThread ot = new OddThread(n);
et.start();
ot.start();
}
}
class EvenThread extends Thread {
private Number number;
public EvenThread(Number number) {
this.number = number;
}
#Override
public void run() {
for(int i=0; i<5; i++) {
System.out.println(number.getEven());
}
}
}
class OddThread extends Thread {
private Number number;
public OddThread(Number number) {
this.number = number;
}
#Override
public void run() {
for(int i=0; i<5; i++) {
System.out.println(number.getOdd());
}
}
}
class Number {
private int currentEven = 0;
private int currentOdd = 1;
private volatile String last = "odd";
public synchronized int getEven() {
if("even".equals(last)) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = currentEven;
last = "even";
currentEven +=2;
notify();
return i;
}
public synchronized int getOdd() {
if("odd".equals(last)) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = currentOdd;
last = "odd";
currentOdd +=2;
notify();
return i;
}
}
and the output is
0
2
1
3
4
5
7
6
8
9
But when I debug the code, it prints the numbers in the correct order. Hence I am not able to figure out what I am missing. Please help me. Thanks in advance for your time for this thread.
As far as I can see, there is nothing preventing this from happening, explaining why 2 is displayed before 1 in your output:
OddThread EvenThread
---------- ----------
gets odd
gets even
prints even
prints odd
The lock therefore needs to be around the whole sequence "get/print".
You'll notice that you are never "two numbers apart" in your output, too.
notify chooses any available thread.
The choice is arbitrary and occurs at the discretion of the implementation
If there are more than two threads waiting you could be signalling the "wrong" thread.
Also, note that both of your threads could be just finished in get(Even|Odd) with neither waiting, leading to the notify going nowhere depending upon the scheduling.
You need to be more strict to ensure the ordering. Perhaps two locks, even and odd, would be helpful.
You need to print the number in getEven and getOdd functions and notify the other thread.
But you were notifying and printing the number, so between noti
Modified code:
public class ThreadExp {
public static void main(String[] args) {
Number n = new Number();
EvenThread et = new EvenThread(n);
OddThread ot = new OddThread(n);
et.start();
ot.start();
}
}
class EvenThread extends Thread {
private Number number;
public EvenThread(Number number) {
this.number = number;
}
#Override
public void run() {
for (int i = 0; i < 10; i++) {
number.getEven();
}
}
}
class OddThread extends Thread {
private Number number;
public OddThread(Number number) {
this.number = number;
}
#Override
public void run() {
for (int i = 0; i < 10; i++) {
number.getOdd();
}
}
}
class Number {
private int currentEven = 0;
private int currentOdd = 1;
private StringBuilder odd;
private StringBuilder even;
private StringBuilder last;
{
odd = new StringBuilder("odd");
even = new StringBuilder("even");
last = odd;
}
public synchronized void getEven() {
if (last == even) {
try {
//System.out.println("inside if in even--->" +Thread.currentThread());
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//System.out.println("out of if in even--> " + Thread.currentThread());
int i = currentEven;
last = even;
currentEven += 2;
System.out.println(i);
notify();
return;
}
public synchronized void getOdd() {
if (last == odd) {
try {
//System.out.println("inside if in odd--->" +Thread.currentThread());
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//System.out.println("out of if in odd--> " + Thread.currentThread());
int i = currentOdd;
last = odd;
currentOdd += 2;
System.out.println(i);
notify();
return;
}
}

Java - multithreading and synchronization

I have two very similar programs each trying to run two threads OddThread and EvenThread and trying to print the odd and even numbers in sequence . While the first one works , the second one hangs . Can anyone please pinpoint the bug in the second program ?
The first one which works :
public class ThreadTest {
public static void main(String[] args) {
System.out.println("Odd Even test");
NumHolder objNumHolder = new NumHolder();
Odd o1 = new Odd(objNumHolder, "Odd Number Thread");
Even e1 = new Even(objNumHolder, "Even Number Thread");
o1.start();
e1.start();
}
}
class NumHolder {
private int intCurrNum;
private boolean isEven = false;
public synchronized void printOddNumber(String tname) {
while (isEven == true){
try {
wait();
}catch (InterruptedException e) {
}
}
isEven = true;
System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
public synchronized void printEvenNumber(String tname) {
while (isEven == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
isEven = false;
System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
class Even extends Thread {
private NumHolder objNumHolder;
public Even(NumHolder p_objNumHolder, String name) {
super(name);
objNumHolder=p_objNumHolder;
}
public void run() {
for (int i = 0; i < 10; i++) {
objNumHolder.printEvenNumber(getName());
}
}
}
class Odd extends Thread {
private NumHolder objNumHolder;
public Odd(NumHolder p_objNumHolder,String name) {
super(name);
objNumHolder = p_objNumHolder;
}
public void run() {
for (int i = 0; i < 10; i++) {
objNumHolder.printOddNumber(getName());
}
}
}
The second code which hangs :
class PrintClass {
int intCurrNum;
private boolean isEven = false;
synchronized void printOdd(){
while(isEven){
try{
wait();
}catch(InterruptedException ie){
System.out.println("Interrupted exception in printOdd()");
ie.printStackTrace();
}
isEven = true;
System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
synchronized void printEven(){
while(!isEven){
try{
wait();
}catch(InterruptedException ie){
System.out.println("Interrupted exception in printEven()");
ie.printStackTrace();
}
isEven = false;
System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
}
class ThreadOdd extends Thread {
PrintClass pc = null;
ThreadOdd(PrintClass pc , String name){
super(name);
this.pc = pc;
}
public void run(){
for (int i = 0; i < 10; i++) {
pc.printOdd();
}
}
}
class ThreadEven extends Thread {
PrintClass pc = null;
ThreadEven(PrintClass pc,String name){
super(name);
this.pc = pc;
}
public void run(){
for (int i = 0; i < 10; i++) {
pc.printEven();
}
}
}
public class EvenOddPrintClass {
public static void main(String[] args){
PrintClass pc = new PrintClass();
Thread to = new ThreadOdd(pc,"ThreadOdd");
Thread te = new ThreadEven(pc,"ThreadEven");
to.start();
te.start();
}
}
Thanks.
I suggest you run your code in the debugger and step through both threads. It's very educational. You will see exactly where the error is.
In both versions, isEven starts out as false.
In the first version, printOddNumber will skip the whole while loop, print the odd number, set isEven to true and notify the even thread, which will print the even number and notify the odd thread again etc. in sequence.
In the second version, printOddNumber will skip the whole while loop, including printing the number and notifying the even thread. After 10 attempts it will exit without having printed anything, and leaving the even thread hanging without ever having notified it.
Interesting. So initially the isEven = false. If the printOdd() is called first then the while (isEven) test is false so printOdd() will exit immediately without generating any output. The while loops in your first program only encompass the wait test, not the entire method.
Then when printEven() is called by the other thread, it will call wait() and hang since there is no other thread to call notifyAll().
You only should want the while loop around the wait since you are going to exit after you print out the even or odd number anyway, right? So the logic in the first program is correct.
public class CountDownApp
{
public static void main(String[] args)
{
Thread count1 = new CountDownEven();
Thread count2 = new CountDownOdd();
count1.start();
count2.start();
}
}
class CountDownEven extends Thread
{
public void run()
{
for(int i=10;i>0;i-=2)
{
System.out.print(+i+"-");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class CountDownOdd extends Thread
{
public void run()
{
for(int i=9;i>0;i-=2)
{
System.out.print(+i+"-");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

Categories

Resources