I don't see how the following code produces output that appears to contravene the definition of an object lock. Surely only one thread should be allowed to print the "acquired lock" message yet they both do?
class InterruptThreadGroup {
public static void main(String[] args) {
Object lock = new Object();
MyThread mt1 = new MyThread(lock);
MyThread mt2 = new MyThread(lock);
mt1.setName("A");
mt1.start();
mt2.setName("B");
mt2.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
// Thread.currentThread().getThreadGroup().interrupt();
}
}
class MyThread extends Thread {
private Object lock;
public MyThread(Object l) {
this.lock = l;
}
public void run() {
synchronized (lock) {
System.out.println(getName() + " acquired lock");
try {
lock.wait();
} catch (InterruptedException e) {
System.out.println(getName() + " interrupted.");
}
System.out.println(getName() + " terminating.");
}
}
}
It is because the call to lock.wait() releases the lock, allowing the second thread to enter the synchronized block. Extract from the javadoc
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. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
Note that there are a few issues in your code such as:
you should not wait outside of a while loop
there is no notify anywhere so your wait could last forever
it is a better practice to have your task implement Runnable and pass it as an argument to a Thread's constructor than to extend Thread directly.
Either you should use synchronized block or wait call . using them together will not work. if you use wait call then the lock is released by the object in synchronized block.
So remove the line lock.wait and your programme will work as you want. synchronize block will handle all lock automatically.
if you are using wait then must use notify.
Here is good thread about this: Why must wait() always be in synchronized block
Related
I'm trying to create thread safe queue in java. I've come across this example:
class ProducerConsumer<T> {
private static final int BUFFER_MAX_SIZE = 42;
private List<T> buffer = new LinkedList<>();
synchronized void produce(T value) throws InterruptedException {
while (buffer.size() == BUFFER_MAX_SIZE) {
wait();
}
buffer.add(value);
notify();
}
synchronized T consume() throws InterruptedException {
while (buffer.size() == 0) {
wait();
}
T result = buffer.remove(0);
notify();
return result;
}
}
I'm new to java. In my understanding those two 'synchronized' keywords would prevent contention inside each method, but not when both methods are called simultaneously. E.g. thread P calls produce, locks method, thread C calls consume, locks other method, then one tries to extract element from list, another tries to insert element, thread exception arises.
My question: Is this example broken?
Or maybe I'm missing something and it's ok.
JLS, §17.1 is quite explicit about the mechanism:
...
A synchronized method (§8.4.3.6) automatically performs a lock action when it is invoked; its body is not executed until the lock action has successfully completed. If the method is an instance method, it locks the monitor associated with the instance for which it was invoked (that is, the object that will be known as this during execution of the body of the method). If the method is static, it locks the monitor associated with the Class object that represents the class in which the method is defined. If execution of the method's body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same monitor.
...
Thus, it is guaranteed that at one point in time on one object at most one thread is executing either produce(...) or consume(). It is not possible that, at one point in time, one thread executes produce(...) on an object while another thread executes consume() on the same object.
The call to wait() in consume() releases the intrinsic lock and blocks execution. The call to notify() in produce(...) notifies one wait()ing thread (if any), so it can fight for the lock as soon as the lock is released by the current owner. Notice that a call to notify() does not release the intrinsic lock. It just wakes up a wait()ing thread. This can be made observable with the following code snippet:
class Ideone {
private static final Object lock = new Object();
public static void main(String[] args) {
printWithThreadNamePrefix("Start");
Thread waiter = new Thread(Ideone::waiter);
waiter.start();
// Give waiter some time to a) start and b) acquire the intrinsic lock
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
final Thread notifier = new Thread(Ideone::notifier);
notifier.start();
while (true) {
try {
waiter.join();
break;
} catch (InterruptedException e) {
}
}
printWithThreadNamePrefix("End");
}
private static void waiter() {
synchronized (lock) {
printWithThreadNamePrefix("Waiting...");
while (true) {
try {
lock.wait();
break;
} catch (InterruptedException e) {
}
}
printWithThreadNamePrefix("... done waiting");
}
}
private static void printWithThreadNamePrefix(String msg) {
System.out.println(String.format(
"%s: %s",
Thread.currentThread().getName(),
msg));
}
private static void notifier() {
synchronized (lock) {
printWithThreadNamePrefix("notifying");
lock.notify();
while (true) {
}
}
}
}
Ideone demo
The program will never terminate. Although thread two calls notify(), it then enters an endless loop, never actually releasing the intrinsic lock. Thus, one never has a chance to acquire the intrinsic lock, and the program "hangs" (it is neither a deadlock, nor a livelock, it simply cannot proceed).
The things I recommend to change are:
declare private List<T> buffer additionally as final
call notifyAll() instead of notify() in order to wake all waiting threads (they will still execute sequentially, for details see this question by Sergey Mikhanov and its answers)
I have following Thread example:
class TickTock {
String state; // contains the state of the clock
synchronized void tick(boolean running) {
if(!running) { // stop the clock
state = "ticked";
notify(); // notify any waiting threads
return;
}
System.out.print("Tick ");
state = "ticked"; // set the current state to ticked
notify(); // let tock() run
try {
while(!state.equals("tocked"))
wait(); // wait for tock() to complete
}
catch(InterruptedException exc) {
System.out.println("Thread interrupted.");
}
}
synchronized void tock(boolean running) {
if(!running) { // stop the clock
state = "tocked";
notify(); // notify any waiting threads
return;
}
System.out.println("Tock");
state = "tocked"; // set the current state to tocked
notify(); // let tick() run
try {
while(!state.equals("ticked"))
wait(); // wait for tick to complete
}
catch(InterruptedException exc) {
System.out.println("Thread interrupted.");
}
}
}
class MyThread implements Runnable {
Thread thrd;
TickTock ttOb;
// Construct a new thread.
MyThread(String name, TickTock tt) {
thrd = new Thread(this, name);
ttOb = tt;
thrd.start(); // start the thread
}
// Begin execution of new thread.
public void run() {
if(thrd.getName().compareTo("Tick") == 0) {
for(int i=0; i<5; i++) ttOb.tick(true);
ttOb.tick(false);
}
else {
for(int i=0; i<5; i++) ttOb.tock(true);
ttOb.tock(false);
}
}
}
class ThreadCom {
public static void main(String args[]) {
TickTock tt = new TickTock();
MyThread mt1 = new MyThread("Tick", tt);
MyThread mt2 = new MyThread("Tock", tt);
try {
mt1.thrd.join();
mt2.thrd.join();
} catch(InterruptedException exc) {
System.out.println("Main thread interrupted.");
}
}
}
How it comes that mt2 is waiting for mt1? Is that because mt1 is created before mt2 and therefore enters the synchronized method first? If yes - next question is: Why mt1 calls notify() before wait()? How can be the monitor released without calling wait()?
I understand it this way: mt1: I can not do any more work here so I will wait() and then I notify() mt2.
Now when I am writing this I realized that maybe thread that calls wait() can no longer call any other methods? So maybe that is why notify() needs to be called first?
Can someone please explain it to me? Thank you!
How it comes that mt2 is waiting for mt1?
After mt2 sets the state to "tocked", it waits until it gets changed to "ticked". Only mt1 can do that.
Is that because mt1 is created before mt2 and therefore enters the synchronized method first?
It doesn't matter which thread enters the method first. Each one waits for the other if necessary. If the thread that can make forward progress gets the lock first, it makes forward progress. If the wrong thread gets the lock, it just waits for the other, releasing the lock and allowing that thread to make forward progress.
If yes - next question is: Why mt1 calls notify() before wait()?
Since mt has changed the state and another thread might be waiting for the state to change, it's important to call notify. Calling wait first would be a disaster -- the other thread might be waiting to get notified about the change this thread made and two threads waiting for each other is a deadlock.
How can be the monitor released without calling wait()?
It can't be. But it doesn't matter. The thread will release the monitor either when it is entirely finished or when it's waiting for the other thread. In all other cases, it's actively modifying shared states and you don't want the lock released.
This program works fine by printing alternate numbers via different threads but when all the numbers from 0-9 are printed Why does this program not stop? I have to manually stop my application.
public class EvenOddPrinter implements Runnable{
private AtomicInteger num = new AtomicInteger(0);
private Object lock = new Object();
#Override
public void run() {
synchronized (lock){
while (num.get()<10){
System.out.println(num.getAndAdd(1) + " - "+Thread.currentThread().getName());
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Executor {
public static void main(String[] args) throws InterruptedException {
EvenOddPrinter eop = new EvenOddPrinter();
Thread t1 = new Thread(eop);
Thread t2 = new Thread(eop);
t1.start();
t2.start();
}
}
that's because in the last Thread getting stuck at wait. notifyAll will notify all waiting thread if any there and release lock.
while (num.get()<10){
// existing implementation
}
lock.notifyAll();
The second thread t2 keeps waiting on the lock in the end, and t1 doesnt do the notify() anymore because the while condition becomes false. You must put a lock.notify(); statement outside of the while loop.
As soon as the number reached 8 the first thread calls notify() and goes to wait(). Second thread then makes the number 9 and calls notify() and goes to wait(). First thread is then not able to go inside the loop as specified in the condition, therefore, it exits the synchronized and block and finishes but second thread is still waiting. There has to be a mechanism to notifyAll() as soon as one of the threads exits the synchronized block which is exactly what I did.
#Override
public void run() {
synchronized (lock){
while (num.get()<10){
System.out.println(num.getAndAdd(1) + " - "+Thread.currentThread().getName());
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notifyAll();
}
Also, lock is pointless when I am using AtomicInteger (or the other way round).
How can two threads access a synchronized block simultaneously? That is, how can I make one thread give the chance for the other thread to execute a synchronized block, even before this thread finishes the execution of the same synchronized block?
See wait(), notify(), and notifyAll().
Edit: The edit to your question is incorrect. The sleep() method does not release the monitor.
For example:
private static final Object lock = new Object();
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(new One());
executorService.execute(new Two());
}
static class One implements Runnable {
#Override
public void run() {
synchronized (lock) {
System.out.println("(One) I own the lock");
System.out.println("(One) Giving up the lock and waiting");
try {
lock.wait();
} catch (InterruptedException e) {
System.err.println("(One) I shouldn't have been interrupted");
}
System.out.println("(One) I have the lock back now");
}
}
}
static class Two implements Runnable {
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.err.println("(Two) I shouldn't have been interrupted");
}
synchronized (lock) {
System.out.println("(Two) Now I own the lock (Two)");
System.out.println("(Two) Giving up the lock using notify()");
lock.notify();
}
}
}
It sounds like you might want to consider using more than one synchronized block, particularly if there's a blocking operation that one thread is getting caught on and thus blocking another thread that wants to execute something else in the block.
A synchronized block is a block of code which can (by definition) only be accessed by one thread at a time.
Saying that you want another thread to enter this block while another thread also currently processes it, does make the synchronized block scheme useless.
You probably want to split the synchronized block into many other ones.
The only way I can see if one thread calls wait() on monitor object. Then it will release monitor and wait for notification while other thread can execute synchronized block. Then other thread will have to call notify()/notifyAll() so first thread gets monitor back and continue.
A thread can release its monitor using lock.wait(). Another thread can then pick up the monitor and enter the synchronized block.
Example:
public class MultipleThreadsInSynchronizedBlock {
public static void main(String... args) {
final Object lock = new Object();
Runnable runnable = new Runnable() {
public void run() {
synchronized (lock) {
System.out.println("Before wait");
try {
lock.wait();
} catch (InterruptedException e) {
}
System.out.println("After wait");
}
}
};
new Thread(runnable).start();
new Thread(runnable).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
synchronized (lock) {
lock.notifyAll();
}
}
}
This prints:
Before wait
Before wait
After wait
After wait
However it's not a "hack" to allow a mutually exclusive block to be run non-atomically. If you're going to use very low-level synchronization primitives like this you need to know what you're doing.
I've got the following code, which I expected to deadlock after printing out "Main: pre-sync". But it looks like synchronized doesn't do what I expect it to. What happens here?
import java.util.*;
public class deadtest {
public static class waiter implements Runnable {
Object obj;
public waiter(Object obj) {
this.obj = obj;
}
public void run() {
System.err.println("Thead: pre-sync");
synchronized(obj) {
System.err.println("Thead: pre-wait");
try {
obj.wait();
} catch (Exception e) {
}
System.err.println("Thead: post-wait");
}
System.err.println("Thead: post-sync");
}
}
public static void main(String args[]) {
Object obj = new Object();
System.err.println("Main: pre-spawn");
Thread waiterThread = new Thread(new waiter(obj));
waiterThread.start();
try {
Thread.sleep(1000);
} catch (Exception e) {
}
System.err.println("Main: pre-sync");
synchronized(obj) {
System.err.println("Main: pre-notify");
obj.notify();
System.err.println("Main: post-notify");
}
System.err.println("Main: post-sync");
try {
waiterThread.join();
} catch (Exception e) {
}
}
}
Since both threads synchronize on the created object, I expected the threads to actually block each other. Currently, the code happily notifies the other thread, joins and exits.
Calling .wait() on a monitor actually releases the synchronized lock so the other thread can lock on to the same monitor and send a notification.
Your behavior is completly normal: "waiter" locks on a monitor and then releases the lock when waiting for notification. After 1 second the main thread locks the monitor, sends notification, unlocks the monitor, which wakes the waiter to complete its operation.
When you wait() on an object, the thread releases the lock on the object to allow others to aquire the lock and notify() the waiting thread. See the javadoc for Object.wait().
The current thread must own this object's monitor. 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. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.