Multithreading with the thread join - java

I work in the multithreading problem where 2 threads are started from the main. The code is provided below,
package com.multi;
public class App {
private int count = 0;
public void doWork() {
Thread thread1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count is: " + count);
}
public static void main(String[] args) {
App worker = new App();
worker.doWork();
}
}
In the book, it informs that there is a possibility that the count value can be printed less than 20000 in some cases. They provided some explanation but even after reading for few times, I was unable to comprehend that completely. Like there is a try block that join the threads and that meant to ensure to complete both for loops.
a. In which circumstances, the count can be printed less than the 20000 and why both of the threads won't increase the count value?
b. If I wrote like
private volatile int count = 0;
private AtomicInteger count = 0;
will these essentially solve the issue?

Consider this sequence
count is 1
thread1 reads count 1 into local var x
thread2 reads count 1 into local var y
thread1 increments x to 2
thread1 writes x value 2 to count
thread2 increments y to 2
thread2 writes the y value 2 to count
When you do count++, it is a read from the field count, an addition of 1 to the value, and then a write of the result back to the field count, so my example sequence is essentially what can happen in your code.
In my example sequence, even though the field was incremented twice, the count is just 2, and not 3.
This happens because both threads are reading and writing from the same field at the same time.

Related

This thread program shows me different answers every time

This is a Java Program to Find The Number with Largest Divisors from 1-500000.
public class Medium2 {
static int count1 = 1;
static int count2 = 1;
static int big_count = 0;
static int big = 0;
Main method
public static void main(String[] args) {
Runnable runnable1 = new Runnable() {
public void run() {
The implementation goes here
for (int num = 1; num <= 500000; num++) {
for (int i = 2; i <= num; i++) {
if (num % i == 0) { //Actual Logic
count1++;
}
}
if (count1 > big_count) {
big_count = count1; //Number of Divisors
big = num; //Largest Number
}
count1 = 1;
}
}
};
And the thread execution
Thread thread1 = new Thread(runnable1); //Threads
Thread thread2 = new Thread(runnable1);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException ie) {
;
}
System.out.println("Biggest: " + big + "\nNumber of Divisors for " + big + " = " + big_count);
}
}
But it gives different answers every time. The actual answer is : 498960 and 200 Divisors
Concerning your goal, your implementation should probably have problems. Since big_count and big is common for both threads and don't have any protection when threads are trying to modify those, your program should create errors.
Other than that, you are also not utilizing 2 threads, since both threads are doing calculation from 1 to 500000.
Since your calculation logic seems ok, you should get your desired output when you try with single thread.
If you want it to do by two threads, you can easily try this. (just to verify, not the nicest way)
You should have big_count1, big1 and big_count2, big2. So that variables whose names end with '1' is only using by thread1 and variables whose names end with '2' is only using by thread2.
Assign thread1 to check from 1 to 250000 and thread2 to from 250001 to 500000.
After join() s, just compare big_count1 and big_count2, then you can deduce the final answer. :))

can ayone what is happening at the background

package workouts;
public class synchro {
private int count = 0;
public void counting() {
Thread T1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
Thread T2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
T1.start();
T2.start();
try {
T1.join();
T2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("counting =" + count);
}
public static void main(String[] args) {
synchro sync = new synchro();
sync.counting();
}
}
but when introduced a synchronised method and call it inside run method like below.. the output is 20000 for how many times if u run it..can someone explain the difference between the above and below code
public class synchro {
private int count = 0;
public synchronized void dosinglethread(){
count++;
}
public void counting() {
Thread T1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
dosinglethread();
}
}
});
Thread T2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
dosinglethread();
}
}
});
T1.start();
T2.start();
try {
T1.join();
T2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("counting =" + count);
}
public static void main(String[] args) {
synchro sync = new synchro();
sync.counting();
}
}
When you say count++, three things happen:
The current value of count is retrieved by the VM
The VM increments the value by 1
The new value is put back into count
It's entirely possible that T1 and T2 both get the value of count, then increment it separately, and then but back the result, like so:
Timeslot T1 T2
1 count = 3 ----
2 ---- count = 3
3 3 + 1 = 4 ----
4 ---- 3 + 1 = 4
5 store 4 in count ----
6 ---- store 4 in count
So now, count++ has been called twice, but the value has only increased by one. To prevent this, you have to make the increment atomic. Atomic means that either the entire sequence of operations is executed, or none of it is. Simply put, if two statements are synchronized on the same Object, they will not interleave.
In your second piece of code, dosinglethread() is declared synchronized. This is the equivalent of:
public void dosinglethread() {
synchronized (this) {
count++;
}
}
This means that when one of the threads starts executing it, they acquire a lock on your synchro instance. When the second thread also tries to execute the method, it will see that another thread already owns the lock on this, so it has to wait. When the first thread completes the method, it will release the lock and the other thread can then take it.
So why didn't volatile work? volatile variables will not cause threads to wait until they are available. Instead, when count is volatile and you call count++, the following happens: (Code adapted from Javamex's Tutorial)
int temp;
synchronized (count) {
temp = count;
}
temp = temp + 1;
synchronized (count) {
count = temp;
}
Note that this code is for illustration only: synchronized can not be used on primitives.
It's clear, then, that the threads might still be paused at temp = temp + 1, giving the same problems as when you don't do any synchronization.
For more information, check the tutorial I mentioned.

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.

Why is this not synchronized correctly?

Hi all I have this code:
public class ThreadTester {
public static void main(String args[]) {
Counter c = new Counter();
for (int i = 0; i < 10; i++) {
MyThread a = new MyThread(c);
MyThread b = new MyThread(c);
a.start();
b.start();
}
System.out.println("The value of the balance is " + c.getVal());
}
}
class MyThread extends Thread {
private Counter c;
public MyThread(Counter c){ this.c = c; }
public void run(){ s.increment(); }
}
class Counter {
private int i = 100;
public synchronized void increment(){ i++; }
public synchronized int getVal(){ return i; }
}
Now I thought that this should give the desired result of 120 - however the result seems to fluctuate between 115 and 120. If I add a Thread.sleep(1) after b.start() I always get the desired result of 120. Why does this happen?
It's really been confusing me and I'd appreciate any help I could get, Thanks
You're printing the value of the counter after having started all the threads, and not after all the threads have completed.
Use Thread.join() on all the threads you have started to wait until they've completed, and then print the value. Or use a CountDownLatch. Sleeping gives you the correct result by accident. It allows all the threads to complete, but only because they have so few things to do that sleeping for 1 millisecond is sufficient.
Because threads run in parallel.
You're printing c.getVal() in the main thread before one or more of your other threads has incremented it.
When you sleep, you're allowing the other threads enough time to complete, then printing.
Because not all the threads have completed their increment task by the time you get to the System.out. Injecting the sleep allows the threads to finish before getting to the output.
The reason:
The third Thread (which executes the main()) function gets to the following statement right after starting Threads a and b in random order and that's why you get unpredictable results.
System.out.println("The value of the balance is " + c.getVal());
Next Question:
If I add a Thread.sleep(1) after b.start() I always get the desired result of 120. Why does this happen?
This happens because you stop the main Thread long enough (1 second is a long time in CPU world) to allow Threads a and b to finish.
Solution: Make the main Thread wait until both Threads a and b have finished. One way:
Counter c = new Counter();
for (int i = 0; i < 10; i++) {
MyThread a = new MyThread(c);
MyThread b = new MyThread(c);
a.start();
b.start();
}
a.join(); // wait for thread a to finish
b.join(); // wait for thread b to finish
System.out.println("The value of the balance is " + c.getVal());
You are printing the result potentially before the threads are finished (which is why the results vary). You need to wait until all threads have completed before printing the result.
Restructure your main method as follows:
public static void main(String args[]) {
Counter c = new Counter();
MyThread[] a = MyThread[20];
for (int i = 0; i < 20; i++) {
a[i] = new MyThread(c);
a[i].start();
}
for (int i = 0; i < 20; i++) {
a[i].join();
}
System.out.println("The value of the balance is " + c.getVal());
}
Firstly, I am looping 20 times since your loop iterated 10 times whilst creating two threads (so you were creating 20 threads too). You need to hold on to the references (via the a array) so that the main thread can wait until all the threads have completed (with join). When they have all completed, the correct result is returned.

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