Need to understand wait() and notify() behavior in my example? - java

public class class_Q {
volatile boolean valueSet = false;
volatile int n;
synchronized int get()
{
System.out.println("Now i am in get block and valueset is : "+ valueSet );
if(!valueSet)
{
System.out.println("i am waiting in get block.....and releasing lock ");
try{
wait();
}catch(InterruptedException e)
{
System.out.println( "InterruptedException caught" );
}
}
System.out.println( " value of n now in get block is : " + n );
valueSet=false;
notify();
return n;
}
synchronized void put(int n)
{
System.out.println(" Now i am in Put block and valueset is : "+ valueSet);
if(valueSet)
{
try
{
System.out.println("i am waiting in put block......and releasing lock. ");
wait();
}catch(InterruptedException e)
{
System.out.println( "InterruptedException caught" );
}
}
this.n = n;
valueSet = true;
System.out.println( "the value of n now in put block is : " + n );
notify();
}
}
class Producer implements Runnable{
class_Q q;
Producer(class_Q q)
{
this.q = q;
new Thread( this, "Producer" ).start();
}
public void run()
{
int i = 0;
while(true)
{
q.put(i++);
}
}
}
class Consumer implements Runnable{
class_Q q;
Consumer(class_Q q)
{
this.q = q;
new Thread(this, "Consumer").start();
}
public void run()
{
while(true)
{
q.get();
}
}
}
class PCFixed {
public static void main (String args[])
{
class_Q q = new class_Q();
new Producer(q);
new Consumer(q);
System.out.println( "Press Control-C to stop." );
}
}
*OUTPUT**
Now i am in get block and valueset is : false
i am waiting in get block.....and releasing lock
Press Control-C to stop.
Now i am in Put block and valueset is : false
the value of n now in put block is : 0
the value of n now in get block is : 0
Now i am in get block and valueset is : false
i am waiting in get block.....and releasing lock
Now i am in Put block and valueset is : false
the value of n now in put block is : 1
the value of n now in get block is : 1
After sixth line of my output i am expecting get() thread to wake up (" notify() " ) put() thread. can someone help me understand the logic behind calling get() thread (in other words why it is in get block?)

I have reformatted your code and changed the logging messages so all should be much clearer.
public class Test {
static class class_Q {
volatile boolean valueSet = false;
volatile int n;
synchronized int get() throws InterruptedException {
System.out.println("get entering - valueSet=" + valueSet);
// *** Changed from `if` to `while`
while (!valueSet) {
System.out.println("get waiting");
wait();
}
// Clear to set the value.
valueSet = false;
// Tell any put waits to finish
notify();
System.out.println("get finished - n=" + n);
return n;
}
synchronized void put(int n) throws InterruptedException {
System.out.println("put entering - valueSet=" + valueSet);
// *** Changed from `if` to `while`
while (valueSet) {
System.out.println("put waiting");
wait();
}
this.n = n;
valueSet = true;
System.out.println("put finished - n=" + n);
notify();
}
}
static class Producer implements Runnable {
class_Q q;
Producer(class_Q q) {
this.q = q;
}
public void run() {
int i = 0;
try {
while (true) {
q.put(i++);
System.out.println("put(" + (i-1) + ")");
}
} catch (InterruptedException ex) {
// Just exit the run loop and finish when interrupted.
}
}
}
static class Consumer implements Runnable {
class_Q q;
Consumer(class_Q q) {
this.q = q;
}
public void run() {
try {
while (true) {
int i;
i = q.get();
System.out.println("get(" + i + ")");
}
} catch (InterruptedException ex) {
// Just exit the run loop and finish when interrupted.
}
}
}
public static void main(String args[]) {
class_Q q = new class_Q();
Thread producer = new Thread(new Producer(q));
Thread consumer = new Thread(new Consumer(q));
System.out.println("Press Control-C to stop.");
producer.start();
consumer.start();
}
}
I have made three main changes too. I have made the interrupted mechanism just quit your threads. I have made your blocking tests loop on the blocked state, not just check them (while (x) instead of if (x)). I have made your threads NOT auto-start.
I think if you run this code now the processes should be clearer and you should be able to understand better what is happening. Remember that System.out is a PrintWriter and can therefore be buffered.
The output I get is:
put entering - valueSet=false
put finished - n=0
put(0)
put entering - valueSet=true
put waiting
Press Control-C to stop.
get entering - valueSet=true
get finished - n=0
put finished - n=1
put(1)
put entering - valueSet=true
put waiting
get(0)
get entering - valueSet=true
get finished - n=1
put finished - n=2
put(2)
put entering - valueSet=true
put waiting
get(1)
get entering - valueSet=true
get finished - n=2
get(2)
get entering - valueSet=false
get waiting
put finished - n=3
get finished - n=3
get(3)
get entering - valueSet=false
get waiting
put(3)
put entering - valueSet=false
put finished - n=4
get finished - n=4
get(4)
get entering - valueSet=false
get waiting
put(4)
...

This is classic producer-consumer pattern with blocking queue. Produces writes data to queue and blocks if queue is full (in current implementation size of queue - single element). Consumer reads from queue and blocks (wait) while queue is empty.
1 You calling get() with valueSet = false. It is stops at wait().
2 You calling put() that notify() your queue object and unlock execution of thread that wait in get() method.

After sixth line of my output i am expecting get() thread to wake up (" notify() " ) put() thread. can someone help me understand the logic behind calling get() thread (in other words why it is in get block?)
Producer start, call put, valueSet is false, return from the function, and call put again, valueSet is true so he has to wait... Without a notify in get, then Producer is blocked forever, even if the Consumer has read the written value...
The notify in each is used to signal the other participant which was ahead in the process and which was waiting for the thread which was behind that they are now both as the same spot.

Related

Mutex implementation in Java

I'm currently learning about thread synchronization in Java and chose to do some tests of my own. The program contains a few threads that access a method to add 1 to a shared int and print which thread just used the method and what the new value of x is. The goal is to have the threads count up from 0 to 10 and print it in the right order like this:
public int addNumbers() {
x++;
if (x >= 10) {
running = false;
}
return x;
}
Thread:
private class RunThread extends Thread {
public void run() {
while (running) {
System.out.println(addNumbers());
}
}
}
In order to create Mutex I've used an ReentrantLock which I've played around with but I have some questions:
Why does this guarantee Mutex and makes the thread print the numbers in the right order...:
lock.lock();
System.out.println(addNumbers());
lock.unlock();
... while this does not?:
public int addNumbers() {
lock.lock();
try {
x++;
if (x >= 10) {
running = false;
}
return x;
} finally {
lock.unlock();
}
}
It looks like it does the same thing to me. And why does it suddenly work when I add a Thread.sleep in the method?:
public int addNumbers() {
lock.lock();
try {
x++;
if (x >= 10) {
running = false;
}
return x;
} finally {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}
}
I've tried to read up on it online, but it just doesn't make any sense to me.
Please help and be kind, I've only just started to learn about multithreading.
Expected "right" results (Counts up normally):
1
2
3
4
5
6
7
8
9
10
11
Wrong results:
2
3
1
4
5
7
6
9
8
10
Entire code:
public class LockTest {
int x = 0;
boolean running = true;
private final Lock lock = new ReentrantLock();
public static void main(String[] args) {
LockTest t1 = new LockTest();
}
public LockTest() {
init();
}
public int addNumbers() {
x++;
if (x >= 10) {
running = false;
}
return x;
}
private void init() {
Thread t1 = new RunThread();
Thread t2 = new RunThread();
Thread t3 = new RunThread();
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
private class RunThread extends Thread {
public void run() {
while (running) {
lock.lock();
System.out.println(this.getName() + ": " + addNumbers());
lock.unlock();
}
}
}
}
In one case, you have
lock.lock();
System.out.println(this.getName() + ": " + addNumbers());
lock.unlock();
So, all threads want to execute these lines concurrently, but only one can do it at a time. So the first thread gets the lock, thus preventing other threads to get it, then increments and prins the value, then releases the lock. Another thread can then get the lock, increment and print, then release the lock. You thus get the values printed in ascending order.
In the second case you only have
System.out.println(this.getName() + ": " + addNumbers());
So, all threads can execute this concurrently. Inside addNumbers, though, the threads must acquire a lock to increment the number. So the number is incremented in the right order, but since the print is not inside the mutex, you have no guarantee of the order. Example:
- Thread 1: acquire the lock
- Thread 1: increment x (x = 1)
- Thread 1: read the value returned by addNumbers (= 1) to print it
- Thread 1: release the lock
- Thread 2: acquire the lock
- Thread 2: increment x (x = 2)
- Thread 2: read the value returned by addNumbers (= 2) to print it
- Thread 2: release the lock
- Thread 2: print the read value: 2
- Thread 1: print the read value: 1

Why is my producer consumer deadlocking (or livelocking)?

I am trying to implement a typical producer consumer using reentrant locks.
Producer thread prints even numbers and consumer threads print odd numbers.
Here is my Code, But for some reason it is deadlocking
The runnable tasks
public class EvenPrinterRunnable implements Runnable {
SharedBuffer buf;
public EvenPrinterRunnable(SharedBuffer buf) {
this.buf = buf;
Thread.currentThread().setName("Even Runnable");
}
#Override
public void run() {
for(int i = 0; i < 10; i++) {
buf.printEven();
}
}
}
public class OddPrinterRunnable implements Runnable {
SharedBuffer buf;
public OddPrinterRunnable(SharedBuffer buf){
this.buf = buf;
Thread.currentThread().setName("ODD Runnable");
}
#Override
public void run(){
for(int i = 0; i < 10; i++){
buf.printOdd();
}
}
}
The shared Buffer
public class SharedBuffer {
Lock lock = new ReentrantLock();
Condition evenNotPrinted = lock.newCondition();
Condition oddNotPrinted = lock.newCondition();
int currentNumber = 0;
public void printEven() {
System.out.println("from even");
try {
lock.lock();
try {
oddNotPrinted.await();
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(" being printed by thread " + "" + Thread.currentThread().getName() + " "+ currentNumber);
currentNumber++;
evenNotPrinted.signalAll();
}
finally {
lock.unlock();
}
}
public void printOdd() {
System.out.println("from odd");
try {
lock.lock();
try {
evenNotPrinted.await();
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(" being printed by thread " + "" + Thread.currentThread().getName() + " "+ currentNumber);
currentNumber++;
oddNotPrinted.signalAll();
}
finally {
lock.unlock();
}
}
}
The driver class
public class OddEvenDriver {
public static void main(String[] args) {
//using runnables with lock buffer
SharedBuffer buf1 = new SharedBuffer();
EvenPrinterRunnable epr = new EvenPrinterRunnable(buf1);
OddPrinterRunnable opr = new OddPrinterRunnable(buf1);
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(opr);
es.submit(epr);
es.shutdown();
}
}
It is outputting
from even
from odd
Or
from odd
from even
That means each thread is acquiring the lock and then it waits on a condition evenNotPrinted and oddNotPrinted, and since no one of them can progress until the signal is called, So my question is , shall I signal each condition at the start of the method itself?
What am i missing here
So my question is , shall I signal each condition at the start of the method itself?
No. That won't work. A condition variable does not remember that it previously was signalled when a thread calls condition.await(). The condition.signal() and condition.signalAll() functions do not do anything at all unless some other thread already is waiting for the signal.
Condition variables are a low-level synchronization mechanism that is intended to be used in a very specific way to implement queues and semaphores and other higher-level synchronized objects. The Guarded Blocks tutorial explains it in detail. (Note: the tutorial talks about object.wait() and object.notify() and synchronized blocks, but the concepts all maps directly onto Lock and Condition objects.)
Your basic problem is that your two threads can't be completely symmetrical with one another. One of them has to go first. Your main() thread must either wake one of them up, or construct one with an argument that says, "you first."

Java threads in order

I'm learning threads so I wanted to make a program which has two types of threads: one that writes random numbers and the other one which checks if the current number matches some specific number. The threads call write() and read(int) methods from the Numbers class. To make things more clear, I want my main program to look like this:
Numbers n = new Numbers();
new WritingThread(n);
new ReadingThread(n,3);
new ReadingThread(n,5);
So the output would be something like this:
2
7
3 !!! MATCH !!!
8
5 !!! MATCH !!!
1
...
The thing is that threads are not executed in order. I want to first execute the WritingThread, and then all the ReadingThreads. Because this way a new random number would be written and only one thread would have the chance to check if the numbers match. Here is the code:
class Numbers:
public class Numbers {
int number;
boolean written = false;
public synchronized void write() {
while (written)
try {
wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
number = (int) (Math.random() * 10);
System.out.print("\n" + number);
written = true;
notifyAll();
}
public synchronized void check(int n) {
while (!written)
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(" Reading thread: " + Thread.currentThread().getName());
if (n == number)
System.out.print(" !!! MATCH !!! ");
notify();
written = false;
}
}
class WritingThread:
public class WritingThread extends Thread {
Numbers n;
WritingThread(Numbers n){
this.n = n;
start();
}
public void run(){
while(true){
n.write();
}
}
}
class ReadingThread:
public class ReadingThread extends Thread{
Numbers n;
int number;
public ReadingThread(Numbers n, int number){
this.n = n;
this.number = number;
start();
}
public void run(){
while(true){
n.check(number);
}
}
}
And the output:
3 Reading thread: Thread-2
3 Reading thread: Thread-1 !!! MATCH !!!
0 Reading thread: Thread-2
5 Reading thread: Thread-1
0 Reading thread: Thread-2
0 Reading thread: Thread-1
5 Reading thread: Thread-2 !!! MATCH !!!
8 Reading thread: Thread-1
I know i could make one thread which has an array of numbers to check, but I am curious how could it be done this way. Thanks.
Lets start with your example. You have two consumers and one boolean flag. Think through the logic. Let's call our three threads W, C1 and C2.
W post 5
W set flag to true
W send notifyAll
C2 awake
C1 awake
C2 acquire lock
C1 block
C2 no match
C2 notify
W awake
W blocks
C2 release lock
C1 acquire lock
flag is false, C1 waits (releases monitor)
flag is false, C2 waits (releases monitor)
GOTO start
This is just one if the many possible ways in which this code can fun. Any time the lock needs to be acquired there is a free for all and of the threads waiting for it only one can get the lock. That thread will check the value set and reset the flag. If that thread is not the one that the value was intended for it is still consumed.
It should be fairly obvious that you have a race hazard. You are using a single queue for two consumer threads. Each consumer thread is fighting for the queue. Your queue is thread safe in that no more than one thread can read the single item from it at any one time but it causes a race hazard as each consumer thread expects to be the only one reading it. If the wrong thread reads the item then the other thread cannot see it.
The only way to resolve this is to have one queue per thread. The producer puts the same item into each consumer thread's private queue and each consumer thread takes items from its queue and reads them.
Here is an example using an ExecutorSerivce:
public static void main(String[] args) throws Exception {
final class Consumer implements Runnable {
private final BlockingQueue<Integer> q = new LinkedBlockingDeque<>();
private final int search;
public Consumer(final int search) {
this.search = search;
}
#Override
public void run() {
while (true) {
try {
if (q.take() == search) {
System.out.println("Found magic number.");
}
} catch (InterruptedException ex) {
return;
}
}
}
public Queue<Integer> getQ() {
return q;
}
}
final class Producer implements Runnable {
final Random r = new Random();
final Iterable<Queue<Integer>> qs;
public Producer(final Iterable<Queue<Integer>> qs) {
this.qs = qs;
}
#Override
public void run() {
while (true) {
final int i = r.nextInt();
for (final Queue<Integer> q : qs) {
q.offer(i);
}
}
}
}
final int numConsumers = 5;
final Collection<Queue<Integer>> qs = new LinkedList<>();
final ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < numConsumers; ++i) {
final Consumer c = new Consumer(i);
qs.add(c.getQ());
es.submit(c);
}
es.submit(new Producer(qs));
}
You are likely to get very few hits with this example as Random.nextInt() is used. If you want to get more hits reduce the range of the generated random numbers by calling Random.nextInt(int max) which generates numbers [0, max).
As you can see each Consumer has a queue of items to check and it blocks using the BlockingQueue API to wait for new items. The Producer puts the same item into each of the Consumer's queues in turn.

Printing Odd and Even number using 2 threads?

I have tried this code. But after printing 0 , it doesn't print anything.
It is blocking due to some lock I think.
public class EvenOdd implements Runnable {
private Object o = new Object();
private volatile int i = 0;
public void run() {
try {
System.out.println();
if ( Thread.currentThread().getName().equals( "Even")) {
printEven();
} else {
printOdd();
}
} catch ( Exception ee) {
ee.printStackTrace();
}
}
private void printEven() throws InterruptedException {
while ( true) {
synchronized ( o) {
while ( this.i % 2 == 0) {
o.wait();
}
System.out.println( Thread.currentThread().getName() + i);
i++;
o.notify();
}
}
}
private void printOdd() throws InterruptedException {
while ( true) {
synchronized ( o) {
while ( this.i % 2 != 0) {
o.wait();
}
System.out.println( Thread.currentThread().getName() + i);
i++;
o.notify();
}
}
}
}
My TestClass:
EvenOdd x = new EvenOdd();
new Thread(x,"Even").start();
new Thread(x,"Odd").start();
Where am I wrong?
Thank.
P.S : I know this type of question has been asked many times , but I want to try by my own.
My guesses is you are;
using one Runnable but both of then think they are even i.e. they both see the first value of 0
printEven has to wait for an odd number ad printOdd has to wait for an even number
EDIT: After running the code the OP fixed the code, it prints
0
1
as expected. It may sometimes print 0 and 0 randomly as the first check for odd/even is not synchronized.
It's a simple deadlock:
Thread 1 waits for someone to notify on the lock. Thread 2 waits for someone to notify on the same lock.
Since no one ever gets to o.notify();, nothing happens.
And i is 0 when both threads start, so both first call printEven(). Now when that has happened, both threads will then call printOdd() in the next round.
The basic concept is when one thread is running, the other has to wait. Once the thread prints the value, it has to wait until the other thread prints. This is achieved by using wait/notify mechanism.
When Odd thread completes printing the value, it notifies the waiting thread(Even thread) and the Even thread becomes ready to run but will wait for the lock to be released by the Odd thread. Now the odd thread calls wait on the locker object so that it releases the lock and goes to wait state. At this point, the only thread waiting for locker object's lock is Even thread and it runs. This process continues alternatively.
public class Test {
public static void main(String[] args) {
Object locker = new Object();
Thread t1 = new Thread(new OddWorker(locker));
Thread t2 = new Thread(new EvenWorker(locker));
t1.start();
t2.start();
}
}
class OddWorker implements Runnable {
private Object locker;
private int number = 1, count = 1;
OddWorker(Object locker) {
this.locker = locker;
}
#Override
public void run() {
synchronized (locker){
do {
try {
System.out.println(Thread.currentThread().getName() + ": " + number);
number += 2;
locker.notify();
locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} while(++count < 11);
locker.notify();
}
}
}
class EvenWorker implements Runnable {
private Object locker;
private int number = 2, count = 1;
EvenWorker(Object locker) {
this.locker = locker;
}
#Override
public void run() {
synchronized (locker){
do {
try {
System.out.println(Thread.currentThread().getName() + ": " + number);
number += 2;
locker.notify();
locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} while(++count < 11);
}
}
}

Reading an array consecutively with two threads

I have an array : int[] arr = {5,4,3,1,2};
I want to do like this::
5 should be read by thread one
4 should be read by thread two
3 should be read by thread one
1 should be read by thread two
2 should be read by thread one
I have tried my best this simple program:
package com.techighost.create.deadlock;
public class ArrayReading implements Runnable {
volatile int index = 0;
int[] arr;
public ArrayReading(int[] arr) {
this.arr = arr;
}
#Override
public void run() {
synchronized (arr) {
for (;index<=(arr.length-1);) {
if (index % 2 == 0 && Thread.currentThread().getName().equals("Thread-One")) {
System.out.println(arr[index] + " " + Thread.currentThread().getName());
index++;
arr.notify();
} else if (index % 2 != 0 && Thread.currentThread().getName().equals("Thread-Two")) {
System.out.println(arr[index] + " " + Thread.currentThread().getName());
index++;
arr.notify();
}else{
System.out.println("In else " + Thread.currentThread().getName());
try {
arr.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
int[] arr = { 5, 4, 3, 1, 2 };
ArrayReading arrayReading = new ArrayReading(arr);
Thread t = new Thread(arrayReading);
t.setName("Thread-One");
Thread t1 = new Thread(arrayReading);
t1.setName("Thread-Two");
t.start();
t1.start();
t.join();
t1.join();
}
}
I think that this thread name check should not be there? Any body please suggest what can be done to remove this check
You can use condition as mentioned by #zzk.Program
for this can be as
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class PrintSequentially {
private final int[] items;
private final ReentrantLock lock;
private final Condition notEven;
private final Condition notOdd;
private int currentCount = 0;
public PrintSequentially(int[] items) {
this.items = items;
this.lock = new ReentrantLock();
this.notEven = lock.newCondition();
this.notOdd = lock.newCondition();
}
public void printSeq() throws InterruptedException {
try {
lock.lockInterruptibly();
while (currentCount < items.length) {
if (currentCount % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":"
+ items[currentCount++]);
if (currentCount < items.length)
notEven.await();
notOdd.signal();
} else {
System.out.println(Thread.currentThread().getName() + ":"
+ items[currentCount++]);
notEven.signal();
if (currentCount < items.length)
notOdd.await();
}
}
} finally {
lock.unlock();
}
}
}
Driver program for this is
public static void main(String[] args) {
int arr[] ={1,2,3,4,5};
final PrintSequentially p = new PrintSequentially(arr);
Runnable r1 = new Runnable() {
#Override
public void run() {
try {
p.printSeq();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
try {
p.printSeq();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread th1 = new Thread(r1);
th1.setName("thread 1");
th1.start();
Thread th2 = new Thread(r2);
th2.setName("thread 2");
th2.start();
}
Here you can add as many thread you want. It will print sequentially.
You could use conditions. Thread 1 should wait for condition index % 2 == 0 and Thread 2 should wait for condition index % 2 == 1.
Look at this link for how to use condition
Use another parameter field in your runnable to tell it to read even or odd indices, create two instances of your runnable, one for even, one for odd. Set up an ExecutorService with at least two threads, execute the runnables. It may be possibile they finish too fast to be given different threads. Did not test this.
I understand that this probably is some sort of getting-your-feet-wet thread application but there are a number of problems with it that makes it less than optimal.
The whole point of using threads is asynchronous operation. Wanting your threads to process every other entry in an array sounds like you are dividing up the work but this may run slower than single threaded because of the synchronization to accomplish the every other. The nature of threads also means that "2" may be printed before "1". That's a good thing because you aren't slowing down a thread to get them to be in order.
Your code has some race conditions here. For example, a thread could process the last element of the list and go to wait but the other thread could have already finished the list and won't be there to notify it. I bet your application often hangs at the end.
You should consider using an executor service and submitting a job for each entry. This is the best way to do most threaded task:
// create a thread pool with 2 workers
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for (int entry : arr) {
threadPool.submit(new `(entry));
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
// to wait for the jobs to finish you do
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
...
Then your ArrayReading takes the entry not the whole array and can work on them independently.
Lastly, as others have already mentioned, you could pass a boolean even flag to have each thread process even (if true) or odd (if false) items.
Thread t1 = new Thread(new ArrayReading(arr, true));
Thread t2 = new Thread(new ArrayReading(arr, false));
You can use inter thread communication using wait and notify like this :
class ReadNum
{
int arr[];
private volatile int counter = 0;
public ReadNum()
{
counter = 0 ;
}
public ReadNum(int size)
{
arr = new int[size];
for (int i = 0; i < size ; i++)
{
arr[i] = i;
}
}
public void setArray(int[] arr)
{
counter = 0;
this.arr = arr;
}
public synchronized void readOdd()
{
while (counter < arr.length)
{
if (counter % 2 != 0)
{
System.out.println(Thread.currentThread().getName()+":->"+arr[counter]);
counter++;
}
notify();
try{
wait();
}catch(Exception ex){ex.printStackTrace();}
}
notify();//So that other EvenThread does'nt hang if OddThread completes earlier
}
public synchronized void readEven()
{
while (counter < arr.length)
{
if (counter % 2 == 0)
{
System.out.println(Thread.currentThread().getName()+":->"+arr[counter]);
counter++;
}
notify();
try{
wait();
}catch(Exception ex){ex.printStackTrace();}
}
notify();//So that other OddThread does'nt hang if EvenThread completes earlier
}
}
public class SequenceRead
{
public static void main(String st[])
{
final ReadNum rn = new ReadNum();
int arr[]= {1,2,34,78,99,45,4545,987,343,45};
rn.setArray(arr);
Thread th1 = new Thread(new Runnable()
{
#Override
public void run()
{
rn.readEven();
}
},"EvenReadThread");
Thread th2 = new Thread( new Runnable()
{
#Override
public void run()
{
rn.readOdd();
}
},"OddReadThread");
th2.start();th1.start();
}
}
UPDATE
Here is the explanation that you asked for about Race Condition.
Race Condition : "It is a situation where multiple threads can access same resource (typically object's instance variables) and can
produce corrupted data if one thread "races in" or "sneaks in" too
quickly before an operation that should be atomic has completed. Hence the output of program is unpredictable because it is dependent on the sequence or timing of starting, execution and completion of the various threads accessing the same resource ."
For example consider the code given below:
class Race
{
private int counter;
public void printCounter()
{
while(counter < 100)
{
try
{
Thread.sleep(10);//Added to show Race Effect.
}
catch (Exception ex){}
counter = counter + 1;
}
System.out.println(Thread.currentThread().getName() +" : "+counter);//If we don't consider Race condition then the Output should be 100 for all threads.
}
}
public class MainClasss
{
public static void main(String st[])
{
final Race race = new Race();
Thread[] th = new Thread[2];
//Creating 2 threads to call printCounter of object race
for (int i = 0 ; i < th.length ; i++)
{
th[i] = new Thread( new Runnable()
{
public void run()
{
race.printCounter();
}
}, "Thread"+i);
}
//Starting all Threads
for (Thread thr : th )
{
thr.start();
}
}
}
And here is the output that that I am getting , It might vary on your system.
Thread1 : 100
Thread0 : 101
All threads are not printing 100 as expected!!! Why ? Because Program has no control on when an executing Thread will be preempted by another thread.It all depends upon JVM Thread Scheduler.One of the possible explanations for above output is as follows:
At counter = 99 , Thread1 sneaked inside the while loop and slept for 10 ms .
JVM Scheduler now preempted Thread1 by Thread0 .
Thread1 goes inside "while" loop because it finds counter < 100
At Thread.sleep Thread0 is preempted by Thread1.
Thread1 increases the counter by 1.
Thread1 prints the counter value as 100 and finishes.
Thread0 continues execution and increases the counter by 1 and makes counter = 101
Thread0 prints the counter value as 101 and finishes.
This is the live exhibition of Race Condition.
To Avoid this Race condition you should make the ReadNum method as synchronized , So that when a Thread enters that method , it takes the monitor and become owner of the synchronized method . And that thread is preempted only after it completes the all operation Atomically . I hope it gave you a good overview of Race Condition now.
here is the code you are looking for ....
public class ThreadConcurrent {
int []array=new int[]{0,1,2,3,4,5,6,7,8,9};
volatile int i=0;
public void checkSum() {
synchronized (this) {
for(;i<array.length;){
System.out.println("thread name "+Thread.currentThread().getName()+ " : "+array[i]);
i++;
notify();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
final ThreadConcurrent er=new ThreadConcurrent();
Thread t1=new Thread(new Runnable() {
#Override
public void run() {
er.checkSum();
}
}, "T1");
Thread t21=new Thread(new Runnable() {
#Override
public void run() {
er.checkSum();
}
}, "T2");
t1.start();
t21.start();
}
}

Categories

Resources