use of wait-notify, whats wrong in my approach - java

I am trying to implement a case of shared variable like semaphores. In that I have 3 thread which should be run sequentially. below is my program. Could u tell me where I am wrong?
class Test2{
private volatile static int sharedvarNEXT = 1;
public synchronized static int getSharedvarNEXT(){
return sharedvarNEXT;
}
public synchronized static void setSharedvarNEXT(int val){
sharedvarNEXT = val;
}
public static void main(String[] s){
new classACaps().start();
new classAsmall().start();
new class1().start();
}
}
class classACaps extends Thread{
public void run(){
try{
for(char c='A';c<='Z';c++){
if(Test2.getSharedvarNEXT() == 1){
System.out.println(c);
Test2.setSharedvarNEXT(2);
notify();
} else {
wait();
}
}
} catch(Exception e){
System.out.println("caught in A");
}
}
}
class classAsmall extends Thread{
public void run(){
try{
for(char c='a';c<='z';c++){
if(Test2.getSharedvarNEXT() == 2){
System.out.println(c);
Test2.setSharedvarNEXT(3);
notify();
} else {
wait();
}
}
} catch(Exception e){
System.out.println("caught in a");
}
}
}
class class1 extends Thread{
public void run(){
try{
for(int c=1;c<=26;c++){
if(Test2.getSharedvarNEXT() == 3){
System.out.println(c);
Test2.setSharedvarNEXT(1);
notify();
}else {
wait();
}
}
} catch(Exception e){
System.out.println("caught in 1");
}
}
}
expected outcome is like : A, a, 1, B, b, 2......

In that I have 3 thread which should be run sequentially.
Well you're not running sequentially - you're running the three concurrently, which is the nature of what happens when you start three separate threads.
Those threads aren't synchronizing against each other at all. It doesn't really sound like you should have three threads at all, given your requirements.
Additionally:
You don't have any synchronized blocks; both wait() and notify() can only be called by a thread which owns the monitor on which they're called
Using wait() and notify() on instances of Thread is strongly discouraged, as the internals of Thread use it themselves. I suggest you create a separate object just to synchronize/wait/notify on.
Your exception handling completely ignores the exception, which has been hiding the first problem from you. Never ignore the exception - and try to avoid catching bare Exception at all, in general.

Calling notify() and wait() inside the run() method is basically calling
this.notify();
None of your Threads is synchronized on each this Thread instance.
You cannot notify() if you don't own the monitor, ie. synchronized on it. You're swallowing all the exceptions you get.

Related

Implementing a "fence" object in Java without using threads

I have been assigned an exercise from my uni professor that goes as follow:
"A fence object is an object that has a collection of objects, and can wait on any of those objects is signaled. There is an add(Object) method, which adds an object to the collection. There is also an await() method: this allows to wait on any object of the collection to be signaled. Whenever the add(Object) method is called while the await() method is active, the argument of the add is put in queue. Write the source code using the following interface: ".
public interface Fence {
public void await() throws InterruptedException;
public void add(Object o);
}
So, only when the same number of notify() and objects in queue (aka the number of add(Object) ) are called, the await() terminates and the object in the queue are finally added to the collection. <- this is something I got wrong and realized after writing my code
I did make the implementation as follow:
import java.util.LinkedList;
public class FenceImpl2 implements Fence{
private LinkedList<Object> collection;
private Object mutex; ;
static boolean iswaiting = false;
public FenceImpl2() {
this.collection = new LinkedList<Object>();
this.mutex = new Object();
}
#Override
public void await() throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
synchronized(mutex) {
mutex.wait();
iswaiting = true;
}
} catch (InterruptedException e) {
e.printStackTrace();
}}});
t1.start();
}
#Override
public void add(Object o) {
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized(mutex){
if(iswaiting == true) {
try {
mutex.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else {
collection.add(o);
}
}}});
t2.start();
}
public Object getList() throws InterruptedException {
synchronized(mutex){
System.out.println("Collection list: \n");
for(Object o : collection) {
System.out.println(o);
Thread.sleep(1000);
}
System.out.println("------- \n");
return collection;
}
}
public void notification() {
Thread thread = new Thread(()->{
synchronized(mutex){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mutex.notify();
}
});
thread.start();
}
public static void main(String[] args) throws InterruptedException {
FenceImpl2 f = new FenceImpl2();
Object o1 = 1;
Object o2 = 2;
Object o3 = 3;
Object o4 = 70;
f.add(o1);
System.out.println("Add 1");
f.add(o2);
System.out.println("Add 2");
f.add(o3);
System.out.println("Add 3");
f.await();
System.out.println("Await active ");
f.add(o4);
System.out.println("Aggiungo 70 - Shouldn't appear. Forced in queue");
f.getList();
f.notification();
System.out.println("Notify() sent - 70 should now appear in the collection");
f.getList();
}
}
After submitting it to my professor I have been told two things:
The synchronization is not correct: the await "unlocks" after the first notify and that shouldn't happen because it doesn't wait for the other (if any) objects that are in queue to be notified.
^Let me say I know how to fix that easily but
Although it's a minor mistake, the methods await, add and notification SHOULD NOT be done using asynchronous dedicated threads.
Here it finally comes my problem. How am I supposed to use wait() on a lock object and then notify() if I am not using dedicated threads?
I tried removing the threads but obviously as soon as I'm calling mutex.wait() the program locks and the code right after that calls the notification method is not reached.
Why did my professor tell me using threads is wrong?
How can I use a wait() and then call a notify() in two separate methods without having the program lock?
Here's an example of what I mean:
public class testw {
private Object mutex;
boolean condition = false;
public testw() {
this.mutex = new Object();
}
public void startWait() {
synchronized(mutex) {
try {
Thread.sleep(1000);
condition = true;
while(condition == true) {
System.out.println("Waiting!");
mutex.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void sendNotify() {
synchronized(mutex) {
try {
Thread.sleep(3000);
System.out.println("Notify!, not waiting anymore");
condition = false;
mutex.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
testw t = new testw();
t.startWait();
t.sendNotify();
}
Without using threads, when I startWait() is called the main thread goes in wait, but there's no way that sendNotify() to be called and the programs freezes. Is there a way to do this without using threads or am I missing something?
Thank you very much.
I have been told...Although it's a minor mistake, the methods await, add and notification SHOULD NOT be done using asynchronous dedicated threads.
The whole point of a method named await() is that it should not return until the event that the caller wants to wait for has happened.
Your await() method doesn't wait. It creates a new thread and then it immediately returns. The new thread waits for something, but after that it just dies without doing anything useful. The new thread might as well not exist at all.
Your add(o) method doesn't make a whole lot of sense either. I'm not even sure what you were trying to do with it, but I think you need to take a step back, and try to explain to the duck why you thought that either of those two methods should create a new thread.
How am I supposed to use wait() on a lock object and then notify() if I am not using dedicated threads?
The Oracle "Guarded Blocks" tutorial is an oldie but a goodie. If you work through it to the end, it should give you a pretty clear idea of how and why and when to use wait() and notify().
https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

Synchronisation of a counter

I try to learn something about multithreading and tried myself on a multithreaded counter. For my knowledge, I synchronized the counter variables but I encounter the following problems:
The threads do not take alternating turns
The counter does not count as intended (eg from 337 to 339 or from 344 to 344)
Can anyone please explain, what I did wrong?
Class RunThreads
public class RunThreads {
public static void main(String[] args) {
Thread thread1 = new Thread1();
Thread thread2 = new Thread2();
thread1.start();
thread2.start();
}
}
Class Thread1
public class Thread1 extends Thread {
public void run(){
while (ThreadCount.counter < 1000){
ThreadCount.incrementCounter();
ThreadCount.printCounter(this);
try{
notifyAll();
wait();
}
catch (Exception e){}
}
}
}
class Thread2 (Yes I don't need two separate classes but it makes it easier for me to understand)
public class Thread2 extends Thread {
public void run(){
while (ThreadCount.counter < 1000){
ThreadCount.incrementCounter();
ThreadCount.printCounter(this);
try{
notifyAll();
wait();
}
catch (Exception e){}
}
}
}
class ThreadCount
public class ThreadCount {
public static int counter = 0;
public static synchronized void incrementCounter(){
counter++;
}
public static void decrementCounter(){
counter--;
}
public static synchronized void printCounter(Thread t){;
Output.append(t.getName() + ":" + counter + "\n");
}
}
class Output
public class Output{
public static String value = "";
public static synchronized void append(String s) {
value+=s;
}
}
This demonstrates the pitfalls of swallowing exceptions. If you caught the exceptions in your threads and simply output them, you would observe the following:
java.lang.IllegalMonitorStateException
at java.base/java.lang.Object.notifyAll
at Thread2.run
This will happen when you call wait and notify/notifyAll on an object (the Thread objects, in this case) where you don't hold the lock by means of synchronized.
If you create a common object that both threads synchronize on, and call wait/notifyAll on, you will get what you are observing. For example:
class Thread1 extends Thread {
public void run(){
synchronized (ThreadCount.lockObj) {
while (ThreadCount.counter < 1000) {
ThreadCount.incrementCounter();
ThreadCount.printCounter(this);
try {
ThreadCount.lockObj.notifyAll();
ThreadCount.lockObj.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
The increment and the print are done in two separate operations.
So you can have (for example)
thread1: increment from 342 to 343
thread2: increment from 343 to 344
thread2: print 344
thread1: print 344
Regarding the alternating turns: both threads call wait() and notifyAll() on themselves (so, on two separate objects), and do so without holding their lock, which throws an exception. And since you ignore exceptions, you can't notice the error you made. Never ignore exceptions. Do not catch Exception.
To have alternating turns, the incrementCounter() method could look like this:
private static boolean turn;
public static synchronized void incrementCounter(){
counter++;
printCounter(Thread.currentThread());
turn = !turn;
boolean nextTurn = !turn;
ThreadCount.class.notifyAll();
while (turn != nextTurn) {
try {
ThreadCount.class.wait();
}
catch (InterruptedException e) {
return;
}
}
}
The turn boolean and the while loop might look averkill, but they're in fact necessary if you want your code to work as expected even in case of spurious wakeups.
*Thread1* ThreadCount.incrementCounter();
*Thread2* ThreadCount.incrementCounter();
*Thread1* ThreadCount.printCounter(this);
*Thread2* ThreadCount.printCounter(this);
In this action Thread 1 increment by 2 and Thread2 increment by 0.
You can use AtomicInteger etc for thread-safe operations.
You should encapsulate int. Don't leave public.

Method synchronized , but code produces random result due to non-serialized thread behaviour

Here is my code:
public class ThreadDemo {
public static void main(String args[]) throws Exception {
Printer[] printers = new Printer[5];
printers[0] = new Printer("#base");
printers[1] = new Printer("#try");
printers[2] = new Printer("!test");
printers[3] = new Printer("^hello");
printers[4] = new Printer("*world");
for (Printer x : printers) {
x.start();
}
try {
for (Printer y : printers) {
y.join();
}
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
class Printer extends Thread {
public Printer(String name) {
super(name);
}
public void run() {
print();
}
public synchronized void print() {
for (int i = 0; i < 10; i++) {
System.out.print(getName().charAt(0));
try {
sleep(100);
} catch (InterruptedException e) {
System.out.println(e + " occured");
}
}
}
}
It results in
#^!#**#^!#*##!^#*#^!#^!*#^*#!##!#*^##^!*!#^#*##*^!
My expectation is that all symbols would be serialized as #####^^^^^ based on which thread starts first.
Calling sleep() would let other threads to proceed until sleeptime of current thread , but i guess that should not be the case with synchronized method.
The synchronised doesn't come into play here.
That keyword makes sure that you can't invoke the same method on the same object in parallel.
You are invoking it on different objects, therefore the result would be the same even without the keyword in place!
( I rather assume that the result you see is in fact caused by using println() here. That is a "really slow" operation that introduces "de facto" synchronisation when used by threads that are super-quick doing all their other work. I am trying to find some additional information about that, but that might take some more time )
The issue with your code or I would say your expectation is that the method print is synchronized at the object level and you are creating new thread objects, starting the thread and calling this method.
So in this case, each method is synchronized on each individual thread object. To achieve the behavior you expect, we can make the print method static and see the behavior change. You will get the expected result because then, the method print is synchronized on a single instance of Printer class lock. So even if different threads instance are calling this method, because there is a single lock for class, thread execution happens sequentially.
public static synchronized void print() {
for (int i = 0; i < 10; i++) {
System.out.print(Thread.currentThread().getName().charAt(0));
try {
sleep(100);
} catch (InterruptedException e) {
System.out.println(e + " occured");
}
}
}
#SolomonSlow - So it has to be corrected as 'No Synchronized methods' can be called on the same object at same time ?
There is only one thing you will ever need to know about a synchronized instance method. You need to know that this...
synchronized void Foobar() { ... }
...Is just a shortcut way of writing a synchronized block.
void Foobar() {
synchronized (this) {
...
}
}
Both of those method declarations do exactly the same thing. So, everything you know or learn about how synchronized blocks behave can be applied to synchronized methods too.
The most important thing to know about synchronized blocks is, "No two threads can ever be synchronized on the same object at the same time." If you understand that, and if you know how a synchronized method is just a shortcut for a synchronized block, then you can answer your own question.

Can a Thread executes further Instructions after invoking target.wait(), without target.notify() is called? [duplicate]

Why doesn't thread wait for notify()? The thread starts and then goes to the waiting pool, but it proceeds to execute after that moment.
public class JavaApplication2 {
public static void main(String [] args) {
ThreadB b = new ThreadB();
synchronized(b) {
b.start();
try {
System.out.println("1");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
#Override
public void run() {
synchronized(this) {
total += 1;
//notify();
}
}
}
You are synchronizing on the thread object itself, which is wrong usage. What happens is that the dying thread-of-execution always calls notify on its Thread object: Thread.join relies on this. Therefore it is clear why you get the same behavior with and without your own notify in there.
Solution: use a separate object for thread coordination; this is the standard practice.
The method notifyAll() is invoked for the Thread object of the terminating thread. This fact is strangely documented in the description of the Thread.join, with the following sentence:
As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
Thus, if you don't explicitly read the description of join, which you don't necessarily have to, you don't get to know the reason for the strange behavior.
You cannot depend on not returning from wait until a notify: "interrupts and spurious wakeups are possible". In general, you should wrap a wait call in a loop while the thread should go on waiting.
If you try your code synchronizing on any object other that ThreadB you will find it never terminates. This is because there is a hidden call to notify.
Although I am not aware of anywhere that this is specified, Thread notifies itself when it ends. This is implicit in the way the join method is implemented. This is the code for join:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
(From the JDK7 source code)
As you can see, the calls to wait only make sense if somewhere there is a call to notify that is called after the thread ends. The same call to notify is what allows your program to terminate.
You have nested synchronized {} constructs in the two places. These constructs seem doing something weird: the thread does not react into notify at all and only resumes when ThreadB (b) terminates. Remove this:
public class JavaApplication2 {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
try {
System.out.println(" ### Waiting for notify");
synchronized (b) {
b.wait();
}
System.out.println(" ### Notified");
} catch (InterruptedException e) {
}
System.out.println("### Total is: " + b.total);
}
}
class ThreadB extends Thread {
int total;
#Override
public void run() {
total += 1;
System.out.println(" *** Ready to notify in 5 secs");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println(" *** Notification sent");
synchronized (this) {
notify();
}
System.out.println(" *** 5 sec post notification");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println(" *** ThreadB exits");
}
}
The code above probably works correctly: with notify() present the main thread resumes after 5 seconds and before we see the message that ThreadB terminates. With notify() commented out the main thread resumes after 10 seconds and after the message about the termination of the ThreadB because notify() is called anywhay from the other code. Marko Topolnik explains why and from where this "behind the scene" notify() call comes from.
I was doing the same testing on the wait/notify opertaions while reading OCP SE 7, good catch. I think we should let the authoer to explain.

Why does java thread wait() work only with time limit in here?

I am trying to get familiar with Java threads for the SCJP and I had a question.
In the below-written code i simply created:
two Runnables with
a common data storage (an array) and
a synchronized write() method to fill it with data successively leaving a letter as a mark for each Runnable (A and B) in sequence.
I know the code is rough and could be better written but I was seeking the moral of the threads.
So now when I run it, it never terminates and the results stop at:
Still good.
A0.
But when I change wait() to wait(100) it works just fine counting from 0 to 9 and it terminates normally. Could someone explain the reason behind that for me please?
Thank you.
public class ArrayThreads {
Object[] array = new Object[10];
boolean isA = true;
int position = 0;
int getIndex(){
return position;
}
class ThreadA implements Runnable{
synchronized void write(String value){
while(!isA){
try {
wait();
} catch (InterruptedException ex) {
System.out.println("An error in" + value);
ex.printStackTrace();
}
}
array[position] = value + position;
System.out.println(array[position]);
position++;
isA = !isA;
notify();
}
public void run() {
while(getIndex()<array.length){
if (getIndex()==9) return;
else
write("A");}
}
}
class ThreadB implements Runnable{
synchronized void write(String value){
while(isA){
try {
wait();
} catch (InterruptedException ex) {
System.out.println("An error in" + value);
ex.printStackTrace();
}
}
array[position] = value + position;
System.out.println(array[position]);
position++;
isA = !isA;
notify();
}
public void run() {
while(getIndex()<array.length){
if (getIndex()==9) return;
else
write("B");}
}
}
public static void main(String[] args){
ArrayThreads threads = new ArrayThreads();
Thread threadA = new Thread(threads.new ThreadA());
Thread threadB = new Thread(threads.new ThreadB());
System.out.println("Still good");
threadB.start();
threadA.start();
}
}
Your threads are each waiting and notifying separate objects - so they're not communicating with each other at all. If you want them to effectively release each other, they'll need a shared monitor to synchronize, wait on and notify.
It's "working" when you specify a timeout because it's effectively turning the wait call into a sleep call... still nothing is really waiting/notifying usefully, because the two threads are still dealing with separate monitors.
your objects are not working in same monitor.
you need to either move the wait() and notify() to same object like:
http://www.java-samples.com/showtutorial.php?tutorialid=306
or you can notify the target object:
http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ315_016.htm
when you set wait(100). you are setting a timeout. and definitely it will wake up after 100ms.

Categories

Resources