this wait/notify code has abnormal performance - java

look the java wait/notify code. I think, will not print false.
But, when I run the code, print false somtime.
Is it java bug?
public class TestThread {
public static volatile String lock = "111";
public static volatile AtomicBoolean flag = new AtomicBoolean(true);
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
public void run() {
try {
while (true) {
synchronized (lock) {
flag.compareAndSet(true, false);
lock.wait();
if (!flag.get()) {
System.out.println(flag.get());
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (lock) {
flag.compareAndSet(false, true);
lock.notify();
}
}
}
}).start();
}
}
console result:
false
false
false

The reason for such a behavior is called spurious wakeup.
Thread may stop waiting and continue it's execution without notify() call. This is a spurious wakeup - a mechanism of operation system thread scheduler.
That's why you always check some condition before calling wait() and set it explicitly before calling notify(). Do not use notify() itself as a guarantee of a job being done.
Example:
Thread 1
synchronized (lock) {
...
while (!condition) {
lock.wait();
}
...
}
Thread 2
synchronized (lock) {
condition = true;
lock.notify();
}

Related

Exercise on synchronization and threads

I'm doing a simple exercise to understand the concept of threads and synchronization. But I don't know whether the code is correct or not.
public class PopcornMachine {
// shared resource
private boolean isBinFull = false;
// producer method
public synchronized void placePopcorn () throws InterruptedException {
while (true) {
while (!isBinFull) wait ();
isBinFull = true;
System.out.println(isBinFull);
notify ();
Thread.sleep(1000);
}
}
// consumer code
public synchronized void takePopcorn () throws InterruptedException {
while (true) {
while (isBinFull) wait ();
isBinFull = false;
System.out.println(isBinFull);
notify ();
Thread.sleep(1000);
}
}
}
public class PopcornDemo {
public static void main (String[] args) throws InterruptedException{
final PopcornMachine machine = new PopcornMachine();
Thread produce = new Thread (new Runnable() {
public void run() {
try {
machine.placePopcorn ();
} catch(InterruptedException e) {}
}
});
Thread consume = new Thread (new Runnable() {
public void run() {
try {
machine.takePopcorn ();
} catch(InterruptedException e) {}
}
});
produce.start();
consume.start();
produce.join();
consume.join();
}
}
The answer I have is:
false
false
false
false
false
false
But it feels wrong. Isn't there a true value should come in the middle of the code?
Change the while condition like below and look at the comments . With your current code producer never executes.
Why? because isBinFull set to false initially and set to false in consumer too
and inside your producer code
while (!isBinFull) wait ();
will be never become false and keep waiting inside while loop.
Change the code like below
public synchronized void placePopcorn () throws InterruptedException {
while (true) {
while (isBinFull) wait(); //Look here, waiting since bin is full
isBinFull = true;
System.out.println(Thread.currentThread().getName() + ":"+isBinFull);
notifyAll ();
Thread.sleep(500);
}
}
// consumer code
public synchronized void takePopcorn () throws InterruptedException {
while (true) {
while (!isBinFull) wait(); ////Look here, waiting since bin is not full
isBinFull = false;
System.out.println(Thread.currentThread().getName() + ":"+isBinFull);
notifyAll ();
Thread.sleep(500);
}
}
using synchronised at method level itself makes sure only one thread executes at a time. synchronised keyword takes lock on the object it is being called i.e. machine in your case and hence the code is not a proper implementation of producer-consumer problem.

Stop a thread and release the lock in Java

I have a ServerState object:
public class ServerState {
public static final LOCK = new ReentrantLock();
public static Map<String, Object> states = new HashMap<>();
}
Thread A:
public class ThreadA extends Thread {
#Override
public void run() {
ServerState.LOCK.lock();
// do some dirty work
ServerState.LOCK.unlock();
}
}
My question is: when thread A has acquired the lock and is doing some dirty work, thread B wants to terminate A immediately but want it release the lock before its terminate, how can I achieve this? I am not looking for use a flag to indicate whether the thread is terminated like this:
public class ThreadA extends Thread {
volatile boolean isFinished = false;
#Override
public void run() {
while (!isFinished) {
ServerState.LOCK.lock();
// do some dirty work
ServerState.LOCK.unlock();
}
}
What I want to achieve is to terminate the thread and release the lock WITHOUT proceeding to the next iteration. Is is possible to do it in Java?
You can use thread interruption mechanism.
If you want to interrupt on LOCK acquiring, you should use LOCK.lockInterruptibly() instead of LOCK.lock():
Thread thread1 = new Thread() {
#Override
void run() {
try {
LOCK.lockInterruptibly();
System.out.println("work");
LOCK.unlock();
} catch (InterruptedException ier) {
this.interrupt()
}
}
};
Then, to stop thread1 just call
thread1.interrupt();
from another thread.
Also I'd suggest to move actual logic from Thread to Runnable:
Thread thread1 = new Thread(
new Runnable() {
#Override
void run() {
try {
LOCK.lockInterruptibly();
System.out.println("work");
LOCK.unlock();
} catch (InterruptedException ier) {
Thread.currentThread().interrupt()
}
}
}
);

Make even and odd threads to print numbers in natural order in Java

I know this question has been asked before, But I am unable to figure out why my solution is not working for me. I have two threads even and odd, one prints even numbers and other prints odd numbers. When I start the threads I want the output to be in natural order of numbers like 0 1 2 3..etc. This is my code:-
[updated]
public class ThreadCommunication {
public static void main(String... args) throws InterruptedException
{
final ThreadCommunication obj = new ThreadCommunication();
Thread even = new Thread(){
#Override
public void run()
{
for(int i=0;i<10;i=i+2){
synchronized(obj){
System.out.println(i);
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
Thread odd = new Thread(){
#Override
public void run()
{
for(int i=1;i<10;i=i+2){
synchronized(obj){
System.out.println(i);
obj.notify();
}
}
}
};
even.start();
odd.start();
}
}
when I run the above code, sometimes it prints the numbers in natural order as expected but sometimes it prints in some other order for ex:
0
1
3
5
7
9
2
What am I doing wrong here?
Edit:
volatile static boolean isAlreadyWaiting = false;
Thread even = new Thread() {
#Override
public void run() {
synchronized (obj) {
for (int i = 0; i < 10; i = i + 2) {
System.out.println(i);
try {
if (!isAlreadyWaiting) {
isAlreadyWaiting = true;
obj.wait();
}
obj.notify();
isAlreadyWaiting=false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Thread odd = new Thread() {
#Override
public void run() {
synchronized (obj) {
for (int i = 1; i < 10; i = i + 2) {
System.out.println(i);
try {
if(isAlreadyWaiting){
obj.notify();
isAlreadyWaiting = false;
}
if (!isAlreadyWaiting) {
isAlreadyWaiting = true;
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Check documentation
public class IllegalMonitorStateException extends RuntimeException
Thrown to indicate that a thread has attempted to wait on an object's
monitor or to notify other threads waiting on an object's monitor
without owning the specified monitor.
Monitor is owned by obj
So you should call
obj.wait();
and
obj.notify();
For more info on Ownership
This methods (wait or notify) should only be called by a thread that
is the owner of this object's monitor. A thread becomes the owner of
the object's monitor in one of three ways:
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes
on the object.
For objects of type Class, by executing a synchronized static method
of that class.
Only one thread at a time can own an object's monitor.
#Pragnani Kinnera is right about the exception you're seeing. But if you want to alternate between even and odd, you'll need to move your second synchronized block into the loop. Otherwise, the notifying thread will hold the lock exclusively until the loop completes. (As opposed to the first thread, which yields its lock on each round.)
Thread odd = new Thread(){
#Override
public void run()
{
for(int i=1;i<10;i=i+2){
synchronized(obj){
System.out.println(i);
notify();
}
}
}
};
The first thread, however, should have the loop inside the synchronized block. If both threads release the lock, they both have an equal chance at reacquiring it. But if the first loop is inside the synchronized block, the second thread won't be able to reenter until the first has completed a full round and is waiting once again.
EDIT: This still won't work correctly, because there is no guarantee that the first thread won't reacquire the lock before the second thread does, per this quote from the documentation:
The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
You'll probably want to wake and notify from both threads to ensure they're in sync.
Here is your solution:
public class ThreadCommunication {
public static void main(String args[]) throws InterruptedException
{
final ThreadCommunication obj = new ThreadCommunication();
Thread even = new Thread("Even Thread"){
#Override
public void run()
{
for(int i=0;i<10;i=i+2){
System.out.println(i);
synchronized(obj){
obj.notify();
}
synchronized(obj){
try {
obj.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Thread odd = new Thread(){
#Override
public void run()
{
for(int i=1;i<10;i=i+2){
try {
synchronized(obj){
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
synchronized(obj){
obj.notifyAll();
}
}
}
};
even.start();
odd.start();
}
}
As explained by #shmosel, your synchronized block should only contain code that need to be synchronized.

Guarded blocks in Java. Where should I update a condition variable?

I'd use a volatile condition variable, but I think volatile is redundant. Besides I'm not quite sure I understood this point from https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility correctly:
An unlock (synchronized block or method exit) of a monitor
happens-before every subsequent lock (synchronized block or method
entry) of that same monitor. And because the happens-before relation
is transitive, all actions of a thread prior to unlocking
happen-before all actions subsequent to any thread locking that
monitor.
So synchronized blocks are called subsequently. But are results of assignments performed in a synchronized block visible to all the subsequent synchronized blocks?
Here is a sample app.
package sample;
public class Foo {
private boolean shouldWait;
private final Object lock = new Object();
void blockThread() {
synchronized (lock) {
shouldWait = true;
while (shouldWait) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
void notifyThread() {
synchronized (lock) {
shouldWait = false;
lock.notify();
}
}
}
Test.
package sample;
public class Main {
private static Foo foo = new Foo();
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
foo.blockThread();
}
}).start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
new Thread(new Runnable() {
#Override
public void run() {
foo.notifyThread();
}
}).start();
}
}
So synchronized blocks are called subsequently. But are results of assignments performed in a synchronized block visible to all the subsequent synchronized blocks?
Yes. volatile writes have the same relationship. All actions prior to a volatile write happens-before all subsequent reads.

Second Thread does not give an output (java)

class firstThread extends Helper1
{
Thread thread_1 = new Thread(new Runnable()
{
#Override
public void run() {
try {
for (int i = 1; i <= 20; i++) {
System.out.println("Hello World");
Thread.sleep(500);
if (i == 10) {
Notify();
Wait();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
class secondThread extends firstThread
{
Thread thread_2 = new Thread(new Runnable()
{
#Override
public void run() {
// TODO Auto-generated method stub
try {
Wait();
for(int i = 1; i<=20; i++)
{
System.out.println("Welcome");
Thread.sleep(100);
}
Notify();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
class Helper1
{
public synchronized void Wait() throws InterruptedException
{
wait();
}
public synchronized void Notify() throws InterruptedException
{
notify();
}
}
public class InheritanceClass {
public static void main(String[] args)
{
Thread f = new Thread(new firstThread().thread_1);
Thread s = new Thread(new secondThread().thread_2);
f.start();
s.start();
}
}
Only the first Thread has an output. Please try my code. I don't know why it happens.
The second thread does not give output, I suppose it's because of Wait() in the secondThread, I don't know what to do.
The problem is with the following code:
class Helper1
{
public synchronized void Wait() throws InterruptedException
{
wait();
}
public synchronized void Notify() throws InterruptedException
{
notify();
}
}
Above, the wait() and notify() calls are equivalent to this.wait() and this.notify(). However, thread1 and thread2 are separate objects so they are not ever going to communicate via this method.
In order for communication to occur, you need a shared lock object. For example:
Object lock = new Object();
firstThread = new firstThread(lock);
secondThread = new secondThread(lock);
and synchronizations like:
void wait(Object lock) {
synchronized(lock) {
lock.wait();
}
}
void notify(Object lock) {
synchronized(lock) {
lock.notify();
}
}
Disclaimer: I would never do this personally, however it does answer the OP's question.
This code is really confusing, which is making it hard to see the underlying problem.
You should never start a class with a lower-case letter since it makes it look like a method/field name (e.g. firstThread).
I'm pretty sure Wait and Notify have no reason to be synchronized.
Why does secondThread inherit from firstThread??? Actually, why do you have those two classes at all? You should just make an anonymous inner class from Helper1 or something.
Anyway, the problem is that when you call Notify() in thread1 it notifies itself, not thread2.

Categories

Resources