waiting threads in a syncronized block - java

if i have these functions
public void methodA(){
synchronized (ObjectAlwaysDifferent) {
....
}
}
public void methodB(){
}
And threads that can enter inside the synchronized block so,
Thread1 enter with Object1
Thread2 enter with Object2
and another thread
Thread3 want to enter with Object1
if thread loop is:
public void run(){
while(true){
methodA();
methodB();
}
}
thread3 will wait inside the methodA,until the lock of object1 will released?
or it ' s able to go to execute the methoB if it's monitor object is locked by another thread?
it is possible to rewrite the methodA() using Lock and condition of (concurrent API)?

Yes, Thread3 would wait until lock gets released.
You are looking for tryLock() from Lock interface
From docs :
boolean tryLock()
Acquires the lock only if it is free at the time of invocation.
Acquires the lock if it is available and returns immediately with the value true. If the lock is not available then this method will return immediately with the value false.
A typical usage idiom for this method would be:
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
This usage ensures that the lock is unlocked if it was acquired, and doesn't try to unlock if the lock was not acquired.
Returns:
true if the lock was acquired and false otherwise

Related

Behavior of wait() and notifyAll() in Java?

Please note that this is not the actual scenario. I created a sample scenario based on my actual implementation, to make it easy to review. I am also already getting the expected output too. However, I need to clarify some concepts regarding the wait() and notifyAll() methods in Java. (In here both these threads will starts there run method at once in the main thread.) So according to my knowledge, since thread B is sleeping, because you can see at the initial stage reamingCount is 400.
So thread B will calls its MUTEX.wait() and continue its sleep until some other thread invokes a notify() or notifyAll(), then after the remainingCount decrements to 0, thread A will call MUTEX.notifyAll(); to awake the thread B and MUTEX.wait() to release its already granted lock, and go to sleep until thread B notifies it.
When I call MUTEX.notifyAll() through thread A, won't thread B wake up and continue its task before thread A calls MUTEX.wait()?
I mean, you can see when thread A calls the MUTEX.notifyAll(), thread B will awake and check again if the condition in the while loop is true or false. So, since the remainingCount is equal to 0, thread B will exit the while loop and continue its task before thread A calls wait(). Won't this scenario break the principle of wait()? According to my knowledge thread B can only continue its execution when thread A calls wait().
public class A implements Runnable{
public static volatile remainingCount =400;
private final Object MUTEX;//Both class A and B holds the same object mutex
private void methodA(){
synchronized(MUTEX){
while(remainingCount == 0){
MUTEX.notifyAll();
MUTEX.wait();
}
//Perform it's usual task.In here remaining count will decrement during the process.
}
#Override
public void run() {
while(true){
methodA();
}
}
}
}
public class B implements Runnable{
private final Object MUTEX;//Both class A and B holds the same object mutex
private void methodB(){
synchronized(MUTEX){
while (A.remainingCount != 0) {
try {
MUTEX.wait();
} catch (InterruptedException ex) {
Logger.getLogger(InkServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
//incrementing the A.remainingCount
MUTEX.notifyAll();
}
#Override
public void run() {
while(true){
methodB();
}
}
}
When a thread holding a lock calls wait() on the locked object, the thread is added to the object's wait set and the lock is released.
When a thread holding a lock calls notify(), and the wait set is not empty, a thread in the wait set is selected and removed. Likewise, calling notifyAll() removes all threads from the wait set.
Note: threads can also be removed from the wait set by a call to thread.interrupt().
When a thread is removed from the wait set and begins to run, the first step is to reacquire the lock. This happens before the return from wait().
This will not happen until the thread that called notify() or notifyAll() releases the lock by either calling wait() or exiting the synchronized block.
So, while your thread B has been enabled to run, it won't actually return from wait() until thread A releases the lock by calling MUTEX.wait(). Likewise, thread A is enabled to run when B calls MUTEX.notifyAll(), but doesn't return from wait() until thread B exits the synchronized(MUTEX) block.

Java synchronization: synchronized, wait(), notify()

I am trying to understand inter-thread communication in Java, and read that the support comes by using: wait(), notify(), notifyAll() methods.
In order thread to execute any of these methods, the thread needs to be owner of object's lock for which thread is invoking (any of these) methods. In addition to this, all these methods needs to be in a synchronized block/method. So far good.
I tried to implement a program in which one thread prints odd numbers, and other thread prints even numbers.
The program works correctly, however, at the same time, it raised few more doubts.
Below is the complete source code of the program which I implemented.
PrintEvenNumThread.java // prints the even numbers
package com.example.multithr.implrun;
import com.example.common.ObjectToWaitOn;
public class PrintEvenNumThread implements Runnable {
private ObjectToWaitOn objectToWaitOn;
public PrintEvenNumThread(ObjectToWaitOn objectToWaitOn) {
this.objectToWaitOn = objectToWaitOn;
}
#Override
public void run() {
int numToPrint = 2;
for (;;) {
synchronized (objectToWaitOn) {
while(objectToWaitOn.getPrintEvenOrOdd() != 2) {
try {
objectToWaitOn.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
objectToWaitOn.print("EvenThread",numToPrint);
numToPrint += 2; // Generate next even number
objectToWaitOn.setPrintEvenOrOdd(1);
objectToWaitOn.notifyAll();
}
}
}
}
PrintOddNumsThread.java // Prints the odd numbers
package com.example.multithr.implrun;
import com.example.common.ObjectToWaitOn;
public class PrintOddNumsThread implements Runnable {
private ObjectToWaitOn objectToWaitOn;
public PrintOddNumsThread(ObjectToWaitOn objectToWaitOn) {
this.objectToWaitOn = objectToWaitOn;
}
#Override
public void run() {
int numToPrint = 1;
for(;;) {
synchronized(objectToWaitOn) {
while(objectToWaitOn.getPrintEvenOrOdd() != 1) {
try {
objectToWaitOn.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
objectToWaitOn.print("OddThread", numToPrint);
numToPrint += 2; // Generate next odd number
objectToWaitOn.setPrintEvenOrOdd(2);
objectToWaitOn.notifyAll();
}
}
}
}
ObjectToWaitOn.java // The "shared" object for inter-thread communication
package com.vipin.common;
public class ObjectToWaitOn {
private int printEvenOrOdd;
public ObjectToWaitOn(int printEvenOrOdd) {
this.printEvenOrOdd = printEvenOrOdd;
}
public int getPrintEvenOrOdd() {
return printEvenOrOdd;
}
public void setPrintEvenOrOdd(int printEvenOrOdd) {
this.printEvenOrOdd = printEvenOrOdd;
}
public void print(String byThread, int numToPrint) {
System.out.println(byThread + ": " +numToPrint);
}
}
PrintEvenOddNumsMainApp.java
package com.example.multithr.main.app1;
import com.example.common.ObjectToWaitOn;
import com.example.multithr.implrun.PrintEvenNumThread;
import com.example.multithr.implrun.PrintOddNumsThread;
public class PrintEvenOddNumsMainApp {
public static void main(String[] args) {
ObjectToWaitOn obj = new ObjectToWaitOn(1); // 1 == odd; 2 == even
PrintEvenNumThread printEvenNumThread = new PrintEvenNumThread(obj);
PrintOddNumsThread printOddNumsThread = new PrintOddNumsThread(obj);
Thread evenNum = new Thread(printEvenNumThread);
Thread oddNum = new Thread(printOddNumsThread);
evenNum.start();
oddNum.start();
}
}
My doubt is:
1) When any of these threads releases lock by calling notifyAll() on object objectToWaitOn (which is shared between these threads), does it release the lock immediately? I have this doubt because these threads are in synchronized block based on objectToWaitOn object; so even if a thread calls the notifyAll(), shouldn't it still hold the lock because it is in synchronized block?
2) When a thread is in waiting condition by calling wait() on objectToWaitOn, and if other thread released the lock by invoking notifyAll(), does the waiting thread waits for lock to release or something else? Doesn't a thread coming out of the synchronized block anyway release the lock on the object it holds; so in above example if a thread is holding lock on objectToWaitOn and comes out of the synchronized block, doesn't it anyway release the lock for objectToWaitOn, and shouldn't based on this the other thread wake up?
Can anyone help me clarify these doubts?
Does it release the lock immediately?
No, it doesn't. The thread continues executing next statements within the synchronisation block.
Shouldn't it still hold the lock because it is in a synchronized block?
Yes, it should. A thread that calls the notify/notifyAll methods must hold the lock and will continue holding it until it leaves the synchronisation block normally or an exception happens:
If execution of the Block completes normally, then the monitor is unlocked and the synchronized statement completes normally.
If execution of the Block completes abruptly for any reason, then the monitor is unlocked and the synchronized statement completes abruptly for the same reason.
JLS-14.19
The notify/notifyAll methods change the state of the threads1 that are waiting on this monitor from State.WAITING to State.RUNNABLE. When the threads are woken up, they can participate in acquiring the lock.
Coming up to the monitor, some of them2 might get the STATE.BLOCKED state and wait until the other thread releases the lock. Note that it doesn't require any notifications from the thread which holds the lock.
The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object. The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
docs
1. In case of notify, it's a single arbitrary chosen thread.
2. Or all of them - if the thread that notified keeps holding the monitor.

What is the purpose of using synchronized (Thread.currentThread())?

Can any one please elaborate why the below code snippet gives IllegalMonitorStateException? I still can't able to find why and when this exception occurs and what is the purpose to lock on the current executing thread instead of object?
void waitForSignal() {
Object obj = new Object();
synchronized (Thread.currentThread()) {
obj.wait();
obj.notify();
}
}
In order to call wait on obj that method/code block should synchronised on obj
void waitForSignal() {
Object obj = new Object();
synchronized (obj) {
obj.wait();
obj.notify();
}
}
You are getting that exception because you need to acquire lock on obj before calling wait(), notify() or notifyAll() methods. These methods are designed to provide a mechanism to allow a thread to block until a specific condition is met.
The wait() method releases lock on the object, that mean you need to have acquired a lock before releasing it.
Whereas notify() and notifyAll() are to notify other threads which are waiting to acquire lock on the same object. It's like one thread is telling other threads : "Dudes, I don't need the object for now, you can go ahead and use it. Make sure you notify me once you are done.".
There are no real scenario where you would want to acquired lock on thread it self.
Here's a code block where you wait for thread to complete before executing a code block.
Thread t = new Thread() {
public void run() {
synchronized (Thread.currentThread()) {
System.out.println("Thread");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
}
};
t.start();
Thread.sleep(10);//sleep main thread
synchronized (t) {
System.out.println("Main Thread");
}
}
I have to sleep main thread becaue, Most of the time synchronized block acquires lock before the thread it self.
You can do the same with join()
synchronized (Thread.currentThread())
doesnt make any sense, a thread cant synchronize itself (that'd produce a deadlock), you will have to synchronize on the OBJECT YOU ARE WAITING FOR:
synchronized (obj)
Also : its always better to use semaphore for this kind of job
Generally speaking locking on the thread makes no sense except for blocking operations on the Thread object itself. For example Thread.join() wait()s on the Thread to finish. This means it uses a synchronised block with wait() to wait on the thread itself.

Synchronized blocks don't work when using member of unrelated class as lock object?

Pretty much all resources I've found on synchronized blocks use this or a member of the class as a lock object. I'm interested in finding out why I can't get synchronized blocks to work when the lock object is a (static) member of another class. Here's my code to illustrate the problem:
public class Test {
public static void main(String[] args) {
Thread thread1 = new FirstThread();
Thread thread2 = new SecondThread();
thread1.start();
thread2.start();
}
}
class FirstThread extends Thread {
#Override
public void run() {
synchronized (Lock.lock) {
System.out.println("First thread entered block");
try {
Lock.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("First thread exited block");
}
}
class SecondThread extends Thread {
#Override
public void run() {
try {
Thread.sleep(1000); //just making sure second thread enters synch block after first thread
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (Lock.lock) {
System.out.println("Second thread entered block");
Lock.lock.notifyAll();
}
System.out.println("Second thread exited block");
}
}
class Lock {
public static Object lock = new Object();
}
My understanding is that the second thread should not be able to enter the synchronized block until the first thread exits, since they are synchronized on the same object. Thus I was expecting the program to hang (deadlock?) after "First thread entered block", since the second thread can't enter the block and the first thread will be stuck waiting for a notification. But instead I got the following output:
First thread entered block
Second thread entered block
Second thread exited block
First thread exited block
Clearly the second thread enters the synchronized block before the first thread has left it's block. Can someone explain what I'm missing?
I thought the purpose of synchronized blocks was to prevent exactly this. Is it because the lock object is a member of another class?
first thread Lock.lock.wait() relinquish the lock on the synchronized object so other thread can enter the critical path and wake up the waiters.
note that sleep(), instead, does not.
Difference between wait() and sleep()
Quote from the javadoc of Object.wait():
The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method.
If that was not the case, waiting would systematically cause a deadlock, since no thread would ever be able to enter the synchronized section needed to call notify() or notifyAll(), making wait and notify completely useless.
When you call lock.wait you "release ownership of this monitor". This allows thread 2 to enter the synchronized block.

Java synchronized blocks -- lock objects

In the sample code
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
on this page,
lock1 and lock2 are controlling the updates on c1 and c2 resply.
However,
synchronized(lock2)
is acquiring the lock of the object lock1 and releasing it when the synchronized block
synchronized(lock1) {
c1++;
}
is executed.
While this block is being executed, there may be
an update on member c1 of this object still-- and I don't
see how this update is being prevented by
synchronizing on lock1 as in the code.
It is the object lock1 that there is exclusive access on--
and nothing else(?)
So, how is the implementation
public void inc1() {
synchronized(lock1) {
c1++;
}
}
in the above code different from
public void synchronized inc1() {
c1++;
}
or even
public void inc1() {
synchronized(c1) {
//do something on c1
}
}
when c1 is an object but not a primitive?
What am I missing here ?
Note: I saw
What is the difference between synchronized on lockObject and using this as the lock?
and
Java synchronized method lock on object, or method?
among some other discussions.
Implementation 1.
You are locking on the lock1 object. Nothing else that needs a lock on lock1 can execute. Having your two methods lock on different objects means that the two methods can run concurrently, but no two threads can run the same method concurrently.
Implementation 2.
Making a method synchronized means that the entire method body is implicitly in a synchronized(this) block (or synchronized on the Class object if the method is static. If both methods are synchronized, then one method would prevent the other from running at the same time, which is different then locking both methods on different objects.
Implementation 3.
If c1 is an object and not a primitive, then the semantics are very similar to implementation 1 - locking on an explicit object.
Marking a block or method synchronized without specifying a lock object synchronizes on the object who owns the method; in this case, the MsLunch instance. It's equivalent to synchronized(this). The purpose of the lock-object idiom is to break that lock up so that c1 and c2 can be manipulated separately. A synchronized block can only synchronize on an object, not a primitive.
synchronized(lock2){
// do sth
}
is actually acquiring lock of object lock2
where as
public void synchronized inc1() {
c1++;
}
acquires object on this object.
locks acquired by synchronized will be released once the program leaves the block.
Your statement is as far as I know incorrect. The page you linked doesn't state what you claim in your question neither. This is how locks work: Locks do not prevent threads of accessing an object at all. Locks only prevents another thread of acquiring the same lock while another thread already has acquired that lock.
This means that this can happen:
Thread A: synchronize (lockObject)
Thread B: lockObject.toString();
Thread A: release the lock on lockObject
This is what happens when two Threads want the same lock at the same time:
Thread A: synchronize (lockObject)
Thread B: synchronize (lockObject) // This will block until (1) !
Thread A: do some stuff and then release lock on lockObject
Thread B: gets the lock (1)
However:
public void synchronized inc1() {
c1++;
}
is exactly the same as:
public void inc1() {
synchronized(this) {
c1++;
}
}
I was having trouble with one thread hogging the lock
for(;;){synchronized(lockObject){
...
}}
I guess Java doesn't like to unlock it on its own the first chance it gets.
Using an java.util.concurrent.locks.ReentrantLock fixed the problem
static ReentrantLock lock = new ReentrantLock();
for(;;){
lock.lock();
...
lock.unlock();
}

Categories