multiple threads call wait(), then notify(), result is deadlock - java

I want to know how I can solve the following problem:
I have created multiple threads of the same kind. They are all have a run-method with a timed while-loop and a synchronized-block, in which wait() is called first, then notify(). This results in all threads staying in wait()-state and none of them calling notify().
How can I overcome this deadlock-situation? Is there a solution using wait()/notify()?
public class Deadlock3 implements Runnable {
LinkedList<Integer> intList;
public Deadlock3(LinkedList<Integer> list) {
intList = list;
new Thread(this).start();
}
public void run() {
long startTime = System.currentTimeMillis();
try {
while (System.currentTimeMillis() - startTime < 10) {
synchronized (intList) {
Integer number = intList.removeFirst();
System.out.println(number + " removed");
number = (number + 3) % 21;
intList.addLast(number);
System.out.println(Thread.currentThread().getName()+" - "+number + " added");
intList.wait();
intList.notifyAll();
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<Integer>();
for (int i = 0; i < 20; i++) {
list.add(i);
}
for (Integer i : list) {
System.out.println(i);
}
for (int i = 0; i < 4; i++) {
new Deadlock3(list);
}
}
}
Thanks for your answers...

How can I overcome this deadlock-situation? Is there a solution using wait()/notify()?
Let's take a look at your code. You start 4 threads by calling new Thread(this).start(); in the constructor of Deadlock3. That's a really bad pattern by the way because the thread can start using the fields before the object has been fully constructed. It is better to do:
for (int i = 0; i < 4; i++) {
new Thread(new Deadlock3(list)).start();
}
But that's not the problem. When the Deadlock3 starts, the first thread synchronizes on intList, does some counting and stuff, and calls intList.wait(). This waits until someone calls intList.notify() or notifyAll(). The first thread goes to sleep waiting and releases the intList lock. The problem is that each thread goes through the same process. They all are waiting on intList and no one reaches the notifyAll().
The real question is what is the point of calling wait() and notify? As I see it you don't need them and they can be removed. If you need them, please explain why?
When I remove those lines and run the program finishes after spitting out a bunch of the following cycles:
...
18 removed
Thread-3 - 0 added
19 removed
Thread-3 - 1 added
20 removed
Thread-3 - 2 added
0 removed
Thread-3 - 3 added
1 removed
Thread-3 - 4 added
2 removed
...
Hope this helps.

Related

Multithreading with the thread join

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.

Why are my threads not synchronizing?

I am trying to get a grasp on synchronizing threads, but I don't understand the problem I'm encountering.
Can someone please help me diagnose this or, even better, explain how I can diagnose this for myself?
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
public class Controller {
public static void main(String[] args) {
int numThreads = 0;
List<Thread> threads = new ArrayList<>();
if (args.length > 0) {
numThreads = Integer.parseInt(args[0]);
}
else {
System.out.println("No arguments");
System.exit(1);
}
CyclicBarrier barrier = new CyclicBarrier(numThreads);
int arr[][] = new int[10][10];
for (int i = 0; i < numThreads; i++) {
Thread newThread = new Thread(new ThreadableClass(barrier, arr));
threads.add(newThread);
}
for (Thread thread : threads) {
thread.start();
}
}
}
There is a main method (above) which accepts the number of threads I want as a command line argument. And there is a work-flow (below) which I am aiming to have increment all elements in a 2D array and print the array before the next thread has its chance to do the same:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class ThreadableClass implements Runnable {
private CyclicBarrier barrier;
private int arr[][];
public ThreadableClass(CyclicBarrier barrier, int[][] arr) {
this.barrier = barrier;
this.arr = arr;
}
#Override
public void run() {
long threadId = Thread.currentThread().getId();
System.out.println(threadId + " Starting");
for (int i = 0; i < 10; i++) {
changeArray();
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
private synchronized void changeArray() {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
arr[i][j]++;
}
}
printArray();
}
private synchronized void printArray() {
System.out.println(Thread.currentThread().getId() + " is printing: ");
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
Imagining the size of the array is 2x2, the expected output would look something like this:
1 1
1 1
2 2
2 2
3 3
3 3
4 4
4 4
...
...
(10 * numThreads)-1 (10 * numThreads)-1
(10 * numThreads)-1 (10 * numThreads)-1
(10 * numThreads) (10 * numThreads)
(10 * numThreads) (10 * numThreads)
Instead, all threads increment the array, and begin printing over one another.
There is nothing surprising about the result. You create n threads. You tell all threads to start. Each threads run() starts with:
long threadId = Thread.currentThread().getId();
System.out.println(threadId + " Starting");
...changeArray();
going to change that shared array. After writing to the array, you try to sync (on that barrier). Its too late then!
The point is: you have 10 different ThreadableClass instances. Each one is operating on its own! The synchronized key word ... simply doesn't provide any protection here!
Because: synchronized prevents two different threads calling the same method on the same object. But when you have multiple objects, and your threads are calling that method on those different objects, than there is no locking! What your code does boils down to:
threadA to call changeArray() .. on itself
threadB to call changeArray() .. on itself
threadC to call changeArray() .. on itself
...
In other words: you give n threads access to that shared array. But then you allow those n threads to enter changeArray() at the same time.
One simple fix; change
private synchronized void changeArray() {
to
private void changeArray() {
synchronized(arr) {
In other words: make sure that the n threads have to lock on the same monitor; in that case the shared array.
Alternatively: instead of making changeArray() a method in that ThreadableClass ... create a class
ArrayUpdater {
int arr[] to update
synchronized changeArray() ...
Then create one instance of that class; and give that same instance to each of your threads. Now the sync'ed method will prevent multiple threads to enter!
Because you are providing new instance for each theard using new ThreadableClass(barrier, arr), basically, all the theadrs are using different ThreadableClass objects, so your code synchronized methods run parallely, so you need to use a single ThreadableClass object as shown below:
ThreadableClass threadableClass= new ThreadableClass(barrier, arr);
for (int i = 0; i < numThreads; i++) {
Thread newThread = new Thread(threadableClass);
threads.add(newThread);
}
The important point is synchronization is all about providing access (i.e., key) to an object for a single thread at a time. If you are using a different object for each thread, threads don't wait for the key because each thread has got its own key (like in your example).

Concurrency in Java using synchronized blocks not giving expected results

Below is a trivial java program. It has a counter called "cnt" that is incremented and then added to a List called "monitor". "cnt" is incremented by multiple threads, and values are added to "monitor" by multiple threads.
At the end of the method "go()", cnt and monitor.size() should have the same value, but they don't. monitor.size() does have the correct value.
If you change the code by uncommenting one of the commented synchronized blocks, and commenting out the currently uncommented one, the code produces the expected results. Also, if you set the thread count (THREAD_COUNT) to 1, the code produces the expected results.
This can only be reproduced on a machine with multiple real cores.
public class ThreadTester {
private List<Integer> monitor = new ArrayList<Integer>();
private Integer cnt = 0;
private static final int NUM_EVENTS = 2313;
private final int THREAD_COUNT = 13;
public ThreadTester() {
}
public void go() {
Runnable r = new Runnable() {
#Override
public void run() {
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
synchronized(cnt) { // <-- is this synchronized necessary?
monitor.add(cnt);
}
// synchronized(cnt) {
// cnt++; // <-- why does moving the synchronized block to here result in the correct value for cnt?
// }
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block here result in cnt being wrong?
}
}
// synchronized(cnt) {
// cnt += NUM_EVENTS; // <-- moving the synchronized block here results in the correct value for cnt, no surprise
// }
}
};
Thread[] threads = new Thread[THREAD_COUNT];
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii] = new Thread(r);
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii].start();
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
try { threads[ii].join(); } catch (InterruptedException e) { }
}
System.out.println("Both values should be: " + NUM_EVENTS*THREAD_COUNT);
synchronized (monitor) {
System.out.println("monitor.size() " + monitor.size());
}
synchronized (cnt) {
System.out.println("cnt " + cnt);
}
}
public static void main(String[] args) {
ThreadTester t = new ThreadTester();
t.go();
System.out.println("DONE");
}
}
Ok let's have a look at the different possibilities you mention:
1.
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
synchronized(cnt) { // <-- is this synchronized necessary?
monitor.add(cnt);
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block to here result in the correct value for cnt?
}
}
First the monitor object is shared between the threads, therefore getting a lock on it (that is what synchronized does) will make sure that the code inside of the block will only be executed by one thread at a time. So the 2 synchronized inside of the outer one are not necessary, the code is protected anyway.
2.
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
monitor.add(cnt);
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block here result in cnt being wrong?
}
}
Ok this one is a little bit tricky. cnt is an Integer object and Java does not allow modifying an Integer object (Integers are immutable) even though the code suggests that this is what is happening here. But what acutally will happen is that cnt++ will create a new Integer with the value cnt + 1 and override cnt.
This is what the code actually does:
synchronized(cnt) {
Integer tmp = new Integer(cnt + 1);
cnt = tmp;
}
The problem is that while one thread will create a new cnt object while all other threads are waiting to get a lock on the old one. The thread now releases the old cnt and will then try to get a lock on the new cnt object and get it while another thread gets a lock on the old cnt object. Suddenly 2 threads are in the critical section, executing the same code and causing a race condition. This is where the wrong results come from.
If you remove the first synchronized block (the one with monitor), then your result gets even more wrong because the chances of a race increase.
In general you should try to use synchronized only on final variables to prevent this from happening.

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.

Categories

Resources