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.
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)
In my current assignment, we are to use a Semaphore to synchronize access to critical sections. However, the provided implementation has me questioning whether it is properly implemented or not. I'd like someone to confirm my worries.
public class Semaphore {
private int iValue;
public Semaphore(int piValue) {
this.iValue = piValue;
}
public Semaphore() {
this(0);
}
public synchronized boolean isLocked() {
return (this.iValue <= 0);
}
public synchronized void P() {
try {
while(this.iValue <= 0) {
wait();
}
this.iValue--;
} catch(InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void V() {
++this.iValue;
notifyAll();
}
}
I believe that there is a possibility for deadlock in this code:
Thread A calls P() and iValue is decremented to 0.
Thread B calls P() before thread A can call V(). The value of iValue is 0, so it enters the while loop.
Thread A now tries to call V(), but cannot because thread B holds the lock. Therefore, there is a deadlock.
Is my conclusion correct?
No.
When you wait the lock is released (you get it back when the wait is over).
Javadoc for 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.
Iam new to syncronization and multithreading please answer why this code is not getting a lock on object b.
public class Tetsclass {
public static void main(String[] args) {
B b = new B();
A a = new A(b);
A2 a2 = new A2(b);
Thread t1= new Thread(a);
Thread t2= new Thread(a2);
t1.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t2.start();
}
}
class B {
public synchronized void waitfor() {
synchronized (B.class) {
System.out.println("Lock aquired on "+System.currentTimeMillis());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Lock released");
}
}
public void readObject() {
System.out.println("readobject by thread==="+Thread.currentThread().getName()+" on "+System.currentTimeMillis());
}
}
class A2 implements Runnable {
B b=null;
public A2(B b) {
this.b = b;
}
#Override
public void run() {
b.readObject();
}
}
class A implements Runnable {
B b=null;
public A(B b) {
this.b = b;
}
#Override
public void run() {
b.waitfor();
}
}
I expected the output :
Lock aquired on 1380016080337
Lock released
readobject by thread===Thread-1 on 1380016082337
but the output is :
Lock aquired on 1380016080337
readobject by thread===Thread-1 on 1380016082337
Lock released
The readObject method, including its invocation from A2#run, involves no lock acquisition. Therefore the lock your other thread is holding is inconsequential to the progress of the execution of readObject.
Apparently you have a misunderstanding of the semantics of locks. You believe that when you lock B.class, you have locked "the whole class". The state of matters is quite different: B.class is just another object, and all objects have their associated monitor, which can be acquired by a thread. Mutual exclusion happens only between threads which contend to acquire one and the same lock. There is no semantic relationship between an object as a lock and any of its methods, and the same stands for class objects vz. instances of that class.
One way your misunderstanding may have arisen is via the objects used implicitly on synchronized methods: a synchronized instance method acquires its this as a lock, while a synchronized static method acquires a lock on its associated class object.
Its behaving as expected.
Here is what happens on the time line
a - calls wait (which sleeps 5 secs before releasing lock)
a2 - calls read which prints read message.
t t+dt t+dt+5
---------|-----------|--------------------------------|--------------------------|----------
[a starts] [print(lock acquired)] [sleeps(5)] [print(lock released)]
t+2
----------------------------|--------------|--------------------------|--------------
[a2 starts] [print(read message)]
There is no locking of any kind in your readObject()
Since the readObject() doesn't require to acquire a lock, it won't wait for the other thread to release the lock. This confusion might have come because of the Thread.sleep(2000) you've in your test class.
Try to change that to Thread.sleep(10000) and see the output. You'll get your desired result.
In the first case, the A2 thread will wait for 2 secs after A starts, and will execute without any further delay whereas your A is held up for 5 secs when it acquired the lock.
In the second case, the A2 thread will wait for 10 secs after A starts, and within those 10 secs, your A will start, sleep for 5 secs and release the lock, after which your A2 will be executed without any delays.
Class B object can be synchronized to get the output as expected. There is no synchronization is involve in current code execution. To synchronized this code and get the expected output, we can modify Class B as
class B {
public synchronized void waitfor() {
synchronized (B.class) {
System.out.println("Lock aquired on "+System.currentTimeMillis());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Lock released");
}
}
public void readObject() {
synchronized(B.class)
{
System.out.println("readobject by thread==="+Thread.currentThread().getName()+" on "+System.currentTimeMillis());
}
}
}
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
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.