Java synchronized block, not all the threads get terminated - java

So I have the following code:
import java.lang.Thread;
import java.lang.Integer;
class MyThread extends Thread {
private int id;
MyThread(int i){
id = i;
}
public void run() {
while(true){
try{
synchronized(Global.lock){
Global.lock.wait();
if(Global.n == 0) {System.out.println(id); Global.lock.notify(); break;}
--Global.n;
System.out.println("I am thread " + id + "\tn is now " + Global.n);
Global.lock.notify();
}
}
catch(Exception e){break;}
}
}
}
class Global{
public static int n;
public static Object lock = new Object();
}
public class Sync2{
public static final void main(String[] sArgs){
int threadNum = Integer.parseInt(sArgs[0]);
Global.n = Integer.parseInt(sArgs[1]);
MyThread[] threads = new MyThread[threadNum];
for(int i = 0; i < threadNum; ++i){
threads[i] = new MyThread(i);
threads[i].start();
}
synchronized(Global.lock){Global.lock.notify();}
}
}
two parameters are entered: a number n and the number of threads to be created. Every thread decreases n by one and then passes control. All threads should stop when n is 0. It seems to work fine so far, but the only problem is that in most of the cases all threads except one terminate. And one is hanging on. Any idea why?
And yes, this is part of a homework, and that is what I've done so far (I was no provided with the code). I'am also explicitly restricted to use a synchronized block and only wait() and .notify() methods by the task.
EDIT: modified the synchronized block a bit:
synchronized(Global.lock){
Global.lock.notify();
if (Global.n == 0) {break;}
if (Global.next != id) {Global.lock.wait(); continue;}
--Global.n;
System.out.println("I am thread " + id + "\tn is now " + Global.n);
Global.next = ++Global.next % Global.threadNum;
}
now threads act strictly in the order they are created. Its pretty unclear from the task wording, but might be the right thing.

You have a race condition. Think about what happens with a single worker thread. Global.n is set to 1 and then the thread starts. It immediately goes into a wait state. Suppose, though, that notify() had already been called on the main thread. Since the worker thread hasn't yet entered a wait state, it isn't notified. Then, when it finally does call wait(), there are no other threads around to call notify(), it stays in the wait state forever. You need to fix up your logic to avoid this race condition.
Also, do you really want a single worker thread to decrement Global.n more than once? That can easily happen with your while (true) ... loop.
EDIT
You also have another logic problem with a single thread. Suppose it enters the wait state and then the notify() in main is called. It wakes the worker thread which decrements Global.n to 0, calls notify(), and then goes back to waiting. The problem is that notify() didn't wake any other thread because there were no other threads to wake. So the one worker thread will wait forever. I haven't analyzed it fully, but something like this might also happen with more than one worker thread.

You should never have a naked wait() call, as semaphores in java are not cached. wait() should always be nested in some sort of
while (condition that you are waiting on)
obj.wait();

Related

My java unit test failed if there is a call to wait method inside a synchronized method

I am learning multi-threads programming in java recently. And I don't understand why the following test case will fail. Any explanation will be much appreciated.
Here is MyCounter.java.
public class MyCounter {
private int count;
public synchronized void incrementSynchronized() throws InterruptedException {
int temp = count;
wait(100); // <-----
count = temp + 1;
}
public int getCount() {
return count;
}
}
This is my unit test class.
public class MyCounterTest {
#Test
public void testSummationWithConcurrency() throws InterruptedException {
int numberOfThreads = 100;
ExecutorService service = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
MyCounter counter = new MyCounter();
for (int i = 0; i < numberOfThreads; i++) {
service.submit(() -> {
try {
counter.incrementSynchronized();
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
}
But if I remove wait(100) from the synchronized method incrementSynchronized, the test will succeed. I don't understand why wait(100) will affect the result.
Solomons suggestion to use sleep is a good one. If you use sleep instead of wait, you should see the test pass.
Using wait causes the thread to relinquish the lock, allowing other threads to proceed and overwrite the value in count. When the thread's wait times out, it acquires the lock again, then writes a value to count that may be stale by now.
The typical usage of wait is when your thread can't do anything useful until some condition is met. Some other thread eventually satisfies that condition and a notification gets sent that will inform the thread it can resume work. In the meantime, since there is nothing useful the thread can do, it releases the lock it is holding (because other threads need the lock in order to make progress meeting the condition that the thread is waiting for) and goes dormant.
Sleep doesn't release the lock so there won't be interference from other threads. For either the sleeping case or the case where you delete the wait call, the lock is held for the duration of the operation, nothing else can change count, so it is threadsafe.
Be aware that in real life, outside of learning exercises, sleeping with a lock held is usually not a great idea. You want to minimize the time that a task holds a lock so you can get more throughput. Threads denying each other the use of a lock is not helpful.
Also be aware that getCount needs to be synchronized as well, since it is reading a value written by another thread.

Beginner's questions about multithreading in Java and usage of synchronized blocks and wait()/notify()

Im learning about synchronization mechanisms in Java. And this an example code that i was given to analyze. Sorry about the missing code, but the story is simple. We have 2 Consumers and 4 Producers who are implemented as Threads and they call these get and put methods respectively in a while loop.
The question is why exactly do we come to a deadlock?
Also, if you could answer me some of questions on my mind.
Is there a difference between the Monitor who deals with threads that communicate with notify and wait and the Monitor who looks after that no two threads enter a synchronization method (get or put)? That is, when one thread inside of the put method calls notify(), is another thread which is waiting to get inside of the put method a valid candidate to take over the Monitor?
Is the answer to my main question so "obvious and dumb" that while one thread is inside wait() of the method put, no other thread can enter both method put and get to notify it which makes the deadlock happen?
What is the difference between notify and notifyAll?
public synchronized void put(Object o) throws InterruptedException {
while (count == size) {
wait();
}
buf[in] = o;
//System.out.println("PUT from " + Thread.currentThread().getName());
++count;
in = (in + 1) % size;
notifyAll(); // if this is not a notifyAll() we might notify the wrong waiter
}
public synchronized Object get() throws InterruptedException {
while (count == 0) {
wait();
}
Object o = buf[out];
buf[out] = null;
//System.out.println("GET from " + Thread.currentThread().getName());
--count;
out = (out + 1) % size;
notifyAll(); // if this is not a notifyAll() we might notify the wrong waiter
return (o);
}
Is the answer to my main question so "obvious and dumb" that while one thread is inside wait() of the method put, no other thread can enter both method put and get to notify it which makes the deadlock happen?
o.wait() performs a sequence of steps:
It releases the lock on o,
It waits until another thread calls o.notify(),
It waits until the lock becomes available again,
It re-locks the lock, and then finally
It returns.
So when one thread is in a wait() call inside a put(o) call, another thread can be executing inside a get() or a put() call.

Wait-Notify synchronized by the same object doesn't work

I made this sample to understand how Wait-Notify works:
public class WaitingTest implements Runnable {
Thread b = new Thread();
int total;
public static void main(String[] args){
WaitingTest w = new WaitingTest();
}
public WaitingTest(){
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + total);
}
}
#Override
public void run(){
synchronized(b){
for(int i=0; i<100 ; i++){
total += i;
System.out.println(total);
}
b.notify();
}
}
}
But I'm stuck here for hours and I can't understand why it's not quite working. My output should be more than 0, but its always zero...I was wondering if its becuase of the usage of different threads, but Im not really sure..What am I missing?
I think you have some serious holes in your understanding. You've declared a Thread
Thread b = new Thread();
and started it in the constructor
b.start();
That Thread will start and die right away since it has no Runnable attached to it.
It just so happens that when a Thread dies, it calls notify() on itself and since you are synchronized on that same Thread object, your wait()ing thread will be awoken. You also have a race here. If the Thread ends before the main thread reaches the wait(), you will be deadlocked.
Also, there is no reason for run() to be called, which is why total remains 0.
Any object can be synchronized on, it doesn't have to be a Thread. And since Thread has that weird behavior of notify()ing itself, you probably shouldn't use it.
You should go through both the Thread tutorials and the synchronization tutorials.
Apart from the problem with how you have arranged your threads, you have a incorrect use of wait()/notify()
notify() is stateless. If no thread is waiting, nothing will be notified. If you wait() later it will not be notified.
wait() can wake spuriously. Just because wait() woke doesn't mean anything notified it.
This means you need to associate wait/notify with state (in fact it's rather pointless without it)
For example.
// to notify
synchronized(lock) {
signalled = true;
lock.notify();
}
// to wait
synchronized(lock) {
while(!signalled)
lock.wait();
}

Java thread join 3

The program creates thread t0 which spawns thread t1 and subsequently threads t2 and t3 are created.After the execution of thread t3and the application never returns to the other threads spawned earlier(t0,t1,t2) and they are left stuck.
Why are the threads t0, t1, and t2 suspended?
public class Cult extends Thread
{
private String[] names = {"t1", "t2", "t3"};
static int count = 0;
public void run()
{
for(int i = 0; i < 100; i++)
{
if(i == 5 && count < 3)
{
Thread t = new Cult(names[count++]);
t.start();
try{
Thread.currentThread().join();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
System.out.print(Thread.currentThread().getName() + " ");
}
}
public static void main(String[] a`)
{
new Cult("t0").start();
}
}
The most important point you missed:
Thread.currentThread().join();
Method join in source code uses isAlive method.
public final synchronized void join(long millis)
...
if (millis == 0) {
while (isAlive()) {
wait(0);
}
...
}
It means that Thread.currentThread().join() will return only when Thread.currentThread() is dead.
But in your case it's impossible because of your running code in Thread.currentThread() has itself
this peace of code Thread.currentThread().join(). That's why after Thread 3 completion your program should hang and nothing happens thereafter.
Why are the threads t0, t1, and t2 suspended? The execution of thread t3 completes.
t3 completes because it is not trying to fork a 4th thread and therefore is not trying to join() with it's own thread. The following line will never return so t0, t1, and t2 all stop there and wait forever:
Thread.currentThread().join();
This is asking the current thread to wait for itself to finish which doesn't work. I suspect that you meant to say t.join(); which is waiting for the thread that was just forked to finish.
Here are some other thoughts about your code in no apparent order:
You should consider implements Runnable instead of extends Thread. See here: "implements Runnable" vs. "extends Thread"
You are using the shared static variable count in multiple threads without any protection of locking. The best solution is to use an AtomicInteger instead of a int. You probably don't have a problem here because each thread is modifying count and then forking another thread but if you tried to fork 2 threads, this would be a real problem because of data race conditions.
I'm not sure why you are only spawning another thread if(i == 5 && count < 3). i is only going to be 5 once in that loop. Is that really what you intended?
String[] names = {"t1", "t2", "t3"}; fields are recommended to be declared at the top of classes. Otherwise they get buried in the code and get lost.
In main you start a Cult thread and then the main thread finishes. This is unnecessary and you can just call cult.run(); in main instead and use the main thread.
Cult(String s) { super(s); } there is no point in having a constructor that calls the super constructor with the same arguments. This can be removed.
This is debatable but I tend to put main method at the top of the class and not bury it since it is the "entrance" method. Same thing with constructors. Those should be above the run() method.
catch(Exception e) {} is a really bad pattern. At the very least you should do a e.printStackTrace(); or log it somehow. Catching and just dropping exceptions hides a lot of problems. Also, catching Exception should be changed to catch(InterruptedException e). You want to restrict your catch blocks just the exceptions thrown by the block otherwise this may again hide problems in the future if you copy and paste that block somewhere.
More a good practice but never use constants like 3 that have to match another data item. In this case it would be better to use names.length which is 3. THis means that you don't need to change 2 places in the code if you want to increase the number of threads. You could also have the name be "t" + count and get rid of the names array altogether.

Difference between notify() and notifyAll()

I know that similar questions have been discussed in this site, but I have not still got further by their aid considering a specific example. I can grasp the difference of notify() and notifyAll() regarding Thread "awakeining" in theory but I cannot perceive how they influence the functionality of program when either of them is used instead of the other. Therefore I set the following code and I would like to know what is the impact of using each one of them. I can say from the start that they give the same output (Sum is printed 3 times).
How do they differ virtually? How could someone modify the program, in order for the applying notify or notifyAll to play a crucial role to its functionality (to give different results)?
Task:
class MyWidget implements Runnable {
private List<Integer> list;
private int sum;
public MyWidget(List<Integer> l) {
list = l;
}
public synchronized int getSum() {
return sum;
}
#Override
public void run() {
synchronized (this) {
int total = 0;
for (Integer i : list)
total += i;
sum = total;
notifyAll();
}
}
}
Thread:
public class MyClient extends Thread {
MyWidget mw;
public MyClient(MyWidget wid) {
mw = wid;
}
public void run() {
synchronized (mw) {
while (mw.getSum() == 0) {
try {
mw.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Sum calculated from Thread "
+ Thread.currentThread().getId() + " : " + mw.getSum());
}
}
public static void main(String[] args) {
Integer[] array = { 4, 6, 3, 8, 6 };
List<Integer> integers = Arrays.asList(array);
MyWidget wid = new MyWidget(integers);
Thread widThread = new Thread(wid);
Thread t1 = new MyClient(wid);
Thread t2 = new MyClient(wid);
Thread t3 = new MyClient(wid);
widThread.start();
t1.start();
t2.start();
t3.start();
}
}
UPDATE:
I write it explicitly. The result is the same whether one uses notify or notifyAll:
Sum calculated from Thread 12 : 27
Sum calculated from Thread 11 : 27
Sum calculated from Thread 10 : 27
Therefore my question: What is the difference?
The difference is subtler than your example aims to provoke. In the words of Josh Bloch (Effective Java 2nd Ed, Item 69):
... there may be cause to use notifyAll in place of notify. Just as placing the wait invocation in a loop protects against accidental or malicious notifications on a publicly accessible object, using notifyAll in place of notify protects against accidental or malicious waits by an unrelated thread. Such waits could otherwise “swallow” a critical notification, leaving its intended recipient waiting indefinitely.
So the idea is that you must consider other pieces of code entering wait on the same monitor you are waiting on, and those other threads swallowing the notification without reacting in the designed way.
Other pitfalls apply as well, which can result in thread starvation, such as that several threads may wait for different conditions, but notify always happens to wake the same thread, and the one whose condition is not satisfied.
Even though not immediately related to your question, I feel it is important to quote this conclusion as well (emphasis by original author):
In summary, using wait and notify directly is like programming in “concurrency assembly language,” as compared to the higher-level language provided by java.util.concurrent. There is seldom, if ever, a reason to use wait and notify in new code. If you maintain code that uses wait and notify, make sure that it always invokes wait from within a while loop using the standard idiom. The notifyAll method should generally be used in preference to notify. If notify is used, great care must be taken to ensure liveness.
This is made clear in all sorts of docs. The difference is that notify() selects (randomly) one thread, waiting for a given lock, and starts it. notifyAll() instead, restarts all threads waiting for the lock.
Best practice suggests that threads always wait in a loop, exited only when the condition on which they are waiting is satisfied. If all threads do that, then you can always use notifyAll(), guaranteeing that every thread whose wait condition has been satisfied, is restarted.
Edited to add hopefully enlightening code:
This program:
import java.util.concurrent.CountDownLatch;
public class NotifyExample {
static final int N_THREADS = 10;
static final char[] lock = new char[0];
static final CountDownLatch latch = new CountDownLatch(N_THREADS);
public static void main(String[] args) {
for (int i = 0; i < N_THREADS; i++) {
final int id = i;
new Thread() {
#Override public void run() {
synchronized (lock) {
System.out.println("waiting: " + id);
latch.countDown();
try { lock.wait(); }
catch (InterruptedException e) {
System.out.println("interrupted: " + id);
}
System.out.println("awake: " + id);
}
}
}.start();
}
try { latch.await(); }
catch (InterruptedException e) {
System.out.println("latch interrupted");
}
synchronized (lock) { lock.notify(); }
}
}
produced this output, in one example run:
waiting: 0
waiting: 4
waiting: 3
waiting: 6
waiting: 2
waiting: 1
waiting: 7
waiting: 5
waiting: 8
waiting: 9
awake: 0
None of the other 9 threads will ever awaken, unless there are further calls to notify.
notify wakes (any) one thread in the wait set, notifyAll wakes all threads in the waiting set. notifyAll should be used most of the time. If you are not sure which to use, then use notifyAll.
In some cases, all waiting threads can take useful action once the wait finishes. An example would be a set of threads waiting for a certain task to finish; once the task has finished, all waiting threads can continue with their business. In such a case you would use notifyAll() to wake up all waiting threads at the same time.
Another case, for example mutually exclusive locking, only one of the waiting threads can do something useful after being notified (in this case acquire the lock). In such a case, you would rather use notify(). Properly implemented, you could use notifyAll() in this situation as well, but you would unnecessarily wake threads that can't do anything anyway.
Javadocs on notify.
Javadocs on notifyAll.
Once only one thread is waiting to sum to not be zero, there is no difference. If there are several threads waiting, notify will wake up only one of them, and all the other will wait forever.
Run this test to better understand the difference:
public class NotifyTest implements Runnable {
#Override
public void run ()
{
synchronized (NotifyTest.class)
{
System.out.println ("Waiting: " + this);
try
{
NotifyTest.class.wait ();
}
catch (InterruptedException ex)
{
return;
}
System.out.println ("Notified: " + this);
}
}
public static void main (String [] args) throws Exception
{
for (int i = 0; i < 10; i++)
new Thread (new NotifyTest ()).start ();
Thread.sleep (1000L); // Let them go into wait ()
System.out.println ("Doing notify ()");
synchronized (NotifyTest.class)
{
NotifyTest.class.notify ();
}
Thread.sleep (1000L); // Let them print their messages
System.out.println ("Doing notifyAll ()");
synchronized (NotifyTest.class)
{
NotifyTest.class.notifyAll ();
}
}
}
I found what is going on with my program. The three Threads print the result even with the notify(), because they do not manage to enter the waiting state. The calculation in the widThread is performed quickly enough to preempt the entering of the other Threads in the waiting state, since it depends on the condition mw.getSum() == 0 (while loop). The widThread calculates the sum, so that the remaining Threads do not ever "see" its value as 0.
If the while loop is removed and the start of widThread comes after the start of the other Threads, then by notify() only one Thread prints the result and the others are waiting forever, as the theory and the other answers indicate.

Categories

Resources