Why did we declare this method synchronized? - java

Consider this class:
// Synchronizing access to shared mutable data using Object
// methods wait and notifyAll.
public class SynchronizedBuffer implements Buffer
{
private int buffer = -1; // shared by producer and consumer threads
private boolean occupied = false;
// place value into buffer
public synchronized void blockingPut(int value) throws InterruptedException
{
// while there are no empty locations, place thread in waiting state
while (occupied)
{
// output thread information and buffer information, then wait
System.out.println("Producer tries to write."); // for demo only
displayState("Buffer full. Producer waits."); // for demo only
wait();
}
buffer = value; // set new buffer value
// indicate producer cannot store another value
// until consumer retrieves current buffer value
occupied = true;
displayState("Producer writes " + buffer); // for demo only
notifyAll(); // tell waiting thread(s) to enter runnable state
} // end method blockingPut; releases lock on SynchronizedBuffer
// return value from buffer
public synchronized int blockingGet() throws InterruptedException
{
// while no data to read, place thread in waiting state
while (!occupied)
{
// output thread information and buffer information, then wait
System.out.println("Consumer tries to read."); // for demo only
displayState("Buffer empty. Consumer waits."); // for demo only
wait();
}
// indicate that producer can store another value
// because consumer just retrieved buffer value
occupied = false;
displayState("Consumer reads " + buffer); // for demo only
notifyAll(); // tell waiting thread(s) to enter runnable state
return buffer;
} // end method blockingGet; releases lock on SynchronizedBuffer
// display current operation and buffer state; for demo only
private synchronized void displayState(String operation)
{
System.out.printf("%-40s%d\t\t%b%n%n", operation, buffer, occupied);
}
} // end class SynchronizedBuffer
And this paragraph from the book:
Notice that method displayState is a synchronized method. This is important because it, too, reads the SynchronizedBuffer’s shared mutable data. Though only one thread at a time may acquire a given object’s lock, one thread may acquire the same object’s lock multiple times—this is known as a reentrant lock and enables one synchronized method to invoke another on the same object.
Why did we declare method the displayState() as synchronized although it's called only from a synchronized method and thus when it's called the calling thread already has the monitor lock on the object?

You are right in questioning this source code. When a method owns the object’s monitor, entering a synchronized method or block acquiring the same monitor again, has no effect at all.
It’s also unlikely that the author considered the possibility that future changes to the code could invoke the method without owning the object’s monitor. First of all, the method’s entire purpose is to report the ongoing operation, second, enforcing correct usage could be achieve even simpler.
It’s also interesting that the method is used inconsistently. The method does always report the current value of buffer, but two of the four callers redundantly append the current value of buffer to the operation argument string before calling the method. Then, there are additional explicit print statements before the two of the callers. Since their message is “[Producer|Consumer] tries to [write|read]”, these statements are very likely supposed to report the attempt before the loop, instead of inside, at a place where it is already known that the attempt failed.
public class SynchronizedBuffer //implements Buffer
{
private int buffer = -1; // shared by producer and consumer threads
private boolean occupied = false;
// place value into buffer
public synchronized void blockingPut(int value)
throws InterruptedException
{
System.out.println("Producer tries to write."); // for demo only
// while there are no empty locations, place thread in waiting state
while(occupied)
{
// output thread information and buffer information, then wait
displayState("Buffer full. Producer waits.", buffer, occupied);// demo only
wait();
}
buffer = value; // set new buffer value
// indicate producer cannot store another value
// until consumer retrieves current buffer value
occupied = true;
displayState("Producer writes ", buffer, occupied); // for demo only
notifyAll(); // tell waiting thread(s) to enter runnable state
} // end method blockingPut; releases lock on SynchronizedBuffer
// return value from buffer
public synchronized int blockingGet() throws InterruptedException
{
System.out.println("Consumer tries to read."); // for demo only
// while no data to read, place thread in waiting state
while(!occupied)
{
// output thread information and buffer information, then wait
displayState("Buffer empty. Consumer waits.", buffer, occupied);// demo only
wait();
}
// indicate that producer can store another value
// because consumer just retrieved buffer value
occupied = false;
displayState("Consumer reads ", buffer, occupied); // for demo only
notifyAll(); // tell waiting thread(s) to enter runnable state
return buffer;
} // end method blockingGet; releases lock on SynchronizedBuffer
// display current operation and buffer state; for demo only
// not accessing the object, hence no synchronization needed
private static void displayState(String operation, int buffer, boolean occupied)
{
System.out.printf("%-40s%d\t\t%b%n%n", operation, buffer, occupied);
}
}
By turning the state to be reported into parameters, the responsibility to access them in a thread safe manner clearly lies at the caller and by making the method static, it’s impossible for the method to incorrectly access object state. Also, redundant reporting of a variable’s value would become apparent at the call site.

Related

How I have here to use the lock and conditions?

here I have a task that I have to use locks and condiitons. In the methods sum() and randomSwap() are the task which I have to complete. So there is enumerated what I have to do. First the class and the task in the methods without my Editings:
public class LockedDataObject extends DataObject {
/** Number of current readers */
int noReaders;
/** True, if writer is currently waiting or writing */
boolean writer;
/**
* Condition variable to put to sleep or wake up the recorder.
*/
Condition condWrite;
/** Condition variable for putting readers to sleep or waking them up */.
Condition condRead;
/**
* Lock to protect all upper variables. Before accessing any of the
* variables is accessed, this lock may need to be acquired. The
* lock should *only be acquired if it is absolutely necessary for correct * execution.
* execution. This is with a changing access
* only if other threads can read or write the corresponding variable * at the same
*time.
* can read or write the corresponding variable at the same time. In the case of a
*reading access
* the lock should not be acquired if other threads can only read * the variable at the
*same time, but not write it.
* read, but not write, access to the corresponding variable at the same time.
* at the same time.
*/
ReentrantLock lock;
public LockedDataObject() {
this.lock = new ReentrantLock();
this.condRead = lock.newCondition();
this.condWrite = lock.newCondition();
this.noReaders = 0;
this.writer = false;
}
public int sum() {
// Note the correct use of the lock variable throughout.
// "lock". Acquire the lock only if it is absolutely necessary.
// 1. as long as a writer is waiting or writing, sleep.
// 2. increase the number of readers by 1.
// 3. sum up
int sum = super.sum();
// 4. decrease the number of readers and, if necessary, wake up the writers.
// 5. return the total
return sum;
}
public void randomSwap() {
// Note the correct use of the lock variable throughout.
// "lock". Acquire the lock only if absolutely necessary.
// 1. indicate that a writer is waiting.
// 2. put to sleep as long as at least one reader is still active.
// 3. swap elements
super.randomSwap();
// 4. indicate that no writer is waiting/writing anymore and
// wake up readers if necessary.
}
}
Now my result:
public int sum() {
// Note the correct use of the lock variable throughout.
// "lock". Acquire the lock only if it is absolutely necessary.
// 1. as long as a writer is waiting or writing, sleep.
while(writer==true) {
lock.lock();
}
// 2. increase the number of readers by 1.
noReaders=noReaders+1;
// 3. sum up
int sum = super.sum();
// 4. decrease the number of readers and, if necessary, wake up the writers.
noReaders=noReaders-1;
try {
condWrite.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 5. return the total
return sum;
}
public void randomSwap() {
// Note the correct use of the lock variable throughout.
// "lock". Acquire the lock only if absolutely necessary.
// 1. show/indicate that a writer is waiting.
//Here I dont now what they want with show that a Writer ist waiting...
// 2. put to sleep as long as at least one reader is still active.
while(writer) {
lock.lock();
}
// 3. swap elements
super.randomSwap();
// 4. indicate that no writer is waiting/writing anymore and
// wake up readers if necessary.
if(writer==false) {
try {
condWrite.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Could someone check, if its correct what I made?

Free all waiting threads

I'm writing this class that simulates a barrier point. When a thread reaches this barrier point it cannot proceed until the other threads have also reached this point. I am using a counter to keep track of the number of threads that have arrived at this point. Assume that the class is expecting N+1 threads, but is only given N threads. In this case the program will keep all the threads waiting because it thinks that there is still one more thread to arrive.
I want to write a method that will allow me to free all of the waiting threads regardless of whether or not the program thinks there is still more threads to arrive at the barrier point.
My program to wait for all threads,
public volatile int count;
public static boolean cycle = false;
public static Lock lock = new ReentrantLock();
public static Condition cv = lock.newCondition();
public void barrier() throws InterruptedException {
boolean cycle;
System.out.println("lock");
lock.lock();
try {
cycle = this.cycle;
if (--this.count == 0) {
System.out.println("releasing all threads");
this.cycle = !this.cycle;
cv.signalAll();
} else {
while (cycle == this.cycle) {
System.out.println("waiting at barrier");
cv.await(); // Line 20
}
}
} finally {
System.out.println("unlock");
lock.unlock();
}
}
I was thinking I could simply create a method that calls the signalAll() method and all the threads would be free. However, a problem I am having is that if the program is expecting more threads it will maintain a lock because it will be waiting at line 20.
Is there a way to get around this lock? How should I approach this problem?
Better idea - use standard java.util.concurrent primitive - CyclicBarrier with method 'reset':
/**
* Resets the barrier to its initial state. If any parties are
* currently waiting at the barrier, they will return with a
* {#link BrokenBarrierException}. Note that resets <em>after</em>
* a breakage has occurred for other reasons can be complicated to
* carry out; threads need to re-synchronize in some other way,
* and choose one to perform the reset. It may be preferable to
* instead create a new barrier for subsequent use.
*/
public void reset()

Java: synchronize object inside another synchronized object

I am trying to get familiar with wait() and notify() methods and I have written a simple class acting like a monitor for a simple producer-consumer excercise where there are N producers and N consumers. Anyway the monitor, as requested in the excercise, can store only 3 items. So the producers must wait; on the contrary if there are 0 items in the monitor the consumers must wait.
public class Monitor {
private List<Integer> items;
private int capacity;
private Object waitProducer;
private Object waitConsumer;
private int counter;
public Monitor() {
this.items = new ArrayList<Integer>();
this.capacity = 3;
this.waitProducer = new Object();
this.waitConsumer = new Object();
this.counter = 0;
}
public void produce() throws InterruptedException {
synchronized (this) {
if (this.items.size() == this.capacity) {
synchronized (this.waitProducer) {
System.out.println("Producer " + Thread.currentThread().getId() + " aspetta");
this.waitProducer.wait(); /***/
}
}
counter++;
System.out.println("Thread " + Thread.currentThread().getId()
+ " produces object " + counter);
this.items.add(counter);
synchronized (this.waitConsumer) {
this.waitConsumer.notify();
}
}
}
public void consume() throws InterruptedException {
synchronized (this) {
if (this.items.size() == 0) {
synchronized (this.waitConsumer) {
this.waitConsumer.wait(); /***/
}
}
System.out.println("Thread " + Thread.currentThread().getId()
+ " consume object " + this.items.get(0));
this.items.remove(0);
synchronized (this.waitProducer) {
this.waitProducer.notify();
}
}
}
}
I think that there is a problem in lines with /***/: infact when the wait() method is invoked then the thread releases the lock on waitProducer (or waitConsumer) but it does not on the Monitor object. That's why when the first produces (of the first consumer) calls wait() then the Monitor object is no more obtainable. Obvioudly the access to the Monitor object must be in mutual exclusion so that to update correctly the list and the counter. So, what is the correct way? Thanks
Only one thread can execute the code inside synchronized blocks at a time.
Also, one must gain an exclusive lock on an object (via synchronized(object)) when calling wait() on that object.
This means, the unlocking/unblocking/notify code must be accessible to other threads outside of original block which called wait(). Otherwise, execution will wait forever.
In your code no other thread can reach this.waitConsumer.notify(); while one thread waits on this.waitProducer.wait();. Because all of it is also enclosed in a synchronized(this) block, other threads will keep contesting for locking on this.
#james large What do you mean that two threads can be synchronized in the same block if they are synchronized on different objects?
Suppose you have a synchronized block that looks like this:
synchronized(obj) {
...body of synchronized block...
}
...whatever happens next...
When Java thread T executes that statement, it starts by evaluating the expression, obj. That expression must either return null, or it must return a reference to an object. If it's null, then a NullPointerException will be thrown. Otherwise, thread T will attempt to lock the object.
No two threads can ever lock the same object at the same time. If the object already was locked by some other thread, then thread T will be unable to proceed until the object is unlocked.
When thread T finally is able to lock the object, it will execute the body of the synchronized block, and then it will unlock the object and move on to whatever happens next.
The important concept here is the expression, obj. Suppose that thread T evaluates obj, gets a reference to object O, locks it, and enters the synchronized block. Then thread U comes along, evaluates obj, gets a different object, P. Thread U will lock object P, and will be able to enter the synchronized block while thread T still is in there at the same time.
So how can that happen?
When it's intended, it might look like this:
class MyClass {
private final Object lock = new Object();
void foobar() {
synchronized(lock) { ... }
}
}
If thread T and thread U are operating on different instances of MyClass, then each instance will have its own lock object. Usually, in this case, the body of the synchronized block will only operate on other instance variables of MyClass. Since the two threads are operating on different data, there is no harm in them both being in the same synchronized block at the same time.
The purpose of synchronization is not to keep two threads out of the same method at the same time: The purpose is to keep two threads from operating on the same data at the same time.
Sometimes a newbie programmer writes this:
static Integer count = new Integer(0);
...
synchronized(count) {
count += 1;
...operate on static data...
}
This is almost always a mistake. When thread T enters the block, it will synchronize on the Integer object that is referenced by the static variable count. But then the next thing it does is update count to refer to a different Integer object. Then along comes thread U. U synchronizes on the new count, and both threads are in the same block, operating on the same static data when they should not.

Does notify/notifyall release the lock being held

I am confused a bit about wait and notify/notifyAll.
I know there is a lock for every java object. I know wait will release the lock for other thread. How about notify/notifyall? Does notify/notifyAll release the lock it is holding for other thread?
No -- notify/notifyAll don't release locks like wait does. The awakened thread can't run until the code which called notify releases its lock.
This is what the Javadoc says:
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.
wait( ) tells the calling thread to give up the monitor and go to sleep until some other
thread enters the same monitor and calls notify( ).
notify( ) wakes up a thread that called wait( ) on the same object.
notifyAll( ) wakes up all the threads that called wait( ) on the same object. The
highest priority thread will run first.
I have to disagree with people who say notifyAll() releases the lock on the object over which waiting and notifying threads are being synchronized.
An example:
Consumer class contains a block:
synchronized(sharedObject){
if(sharedObject.isReadyToConsume() == false){
sharedObject.wait();
}else {
sharedObject.doTheThing();
System.out.println("consumer consuming...");
}
}
Scenario: Consumer class gets the lock on the sharedObject object, enters exclusively (it's inside the sync block) and sees that sharedObject has nothing ready yet (nothing to consume :) ) and it calls wait() method on the sharedObject. That way it releases the lock (stops the execution there!) and waits to be notified to continue when another Thread (Producer maybe) calls sharedObject.notify(); or sharedObject.notifyAll();. When it gets notified it continues from the wait() line
It's the sharedObject that keeps track of threads that asked it to be notified. When some Thread calls sharedObject.notifyAll() method the sharedObject will notify the waiting threads to wake up...
Now, the tricky part is that a thread naturally releases the lock of the object when it reaches the end of its synchronized(sharedObject){} block. THe question is what happens if I call notifyAll() in that block??? notifyAll() wakes up the waiting threads, but the lock is still owned by the Thread that has just call notifyAll()
Look at the Producer snippet:
synchronized(sharedObject){
//We are exlusively working with sharedObject and noone can enter it
[... changing the object ...]
sharedObject.notifyAll(); //notifying the waiting threads to wake up
Thread.sleep(1000); //Telling the current thread to go to sleep. It's holding the LOCK
System.out.println("awake...");
}
If notifyAll() would release the lock then the "awake..." would get printed out after the Consumer classes already start working with the sharedObject. This is not the case... The output shows that the Consumer is consuming the sharedObject after the Producer exits its sync block...
wait() - releases the lock and continues on the next line when it gets notified
notify(), notifyAll() - don't release the lock. They simply make waiting threads runnable again (not idle). They will have the right to enter when the
current thread reaches the end of its sync block and the Thread
scheduleder tells them that the lock has been released. The fight for
the lock begins again
Lets say bunch of Readers wants to read updated Value of certain Resource, which is going to be updated by Writer. Then how Reader knows that Resource Fields have been updated by Writer.
Therefore to Synchronize such cases between Readers and Writers on common resource, three final methods of Object class have been used.
wait()
notify()
notifyAll()
Wait : Readers wants to read updated value of resource, they register with resource object i.e when update happens on same object and when Writer notify it, readers will try to acquire lock on resource and read the updated resource.
- Wait only being invoked when Reader have Lock Object, here in our case it is resource.
- Once wait method is called, Reader releases the Lock Object.
- Now Only for the same registered Object(resource) Reader will get notification signals.
- If Reader invokes wait on Object, which is different from Object Writer used for sending notification, Reader will never gets the notification signal.
- Once Reader(s) are notified, now Reader(s) will try to content for the Lock(one of them gets the lock) read the updated value of resource. Similarly other Readers also gets turn to acquire lock and read the updated value.
- Once Reader read the updated value, perform there Business Logic and come out from Synchronized Block, Reader will release the lock so that other Readers can acquire it.
Notify: Writer enters the Synchronized Block, after acquiring lock performs his Business Logic, update the resource Object, once resource Object is updated it will notify the waiting threads(Readers) whom are waiting on same Lock.
- Notify signal to only one waiting Thread, which is decided by underlying Java Thread Manager
- Once Writer signals notify(), then it doesn't means Reader rushed immediately to read the updates values. Firstly writer must release the Lock, which it will do once it comes out of Synchronized block.Once Lock is being released and waiting threads are notified, then [In case of notify()] notified Thread will acquire the Lock[Released by Writer] and then enter the Synchronized Block and completes from where he left[i.e statements after wait()].
Notify-All: In notifyAll, all threads who are registered with resource lock, will get the notifications.
- Once notifyAll() is triggered, all threads waiting on same lock will get the signal and are ready in contention to acquire the lock.
- Once Writer finishes its Job and release the Lock, Any one Reader will acquire the lock[which Thread, again decided by underlying Java Thread Manager Implementation].
- Once the Reader gets the Lock, it will enter in Synchronized Block, where he left[i.e after wait() method] performs it tasks and on completing the Synchronized Block releases the Lock.
- Now Other remaining Threads will try to acquire the Lock, anyone of them will get it, enters synchronized block, completes its task and then release the Lock.
- This process will keep on till all Registered Readers complete there Job.
Now we will see the Code for it. Also we will discuss the Code also. :
Basic Overview Of code : It consists of Three classes
Resource Class : On which Lock will be acquired and wait() and notify(), notifyAll() will be invoked.
ReaderTask : Implements Runnable interface, implies readers jobs, wants to read updated Value of resource object.
WriterTask : Implements Runnable interface, implies writer jobs, will update the resource object and notify registered waiting threads.
Demo Class: which will create Let say 3 Readers and 1 Writer Thread, Bind Respective Tasks to them and start the threads.
Resource.java
public class Resource {
private String mesg;
public void setMesg(String mesg){
this.mesg =mesg;
}
public String getMesg(){
return this.mesg;
}
}
WaitThreadTask.java
public class WaitThreadTask implements Runnable {
private Resource resource;
public WaitThreadTask(Resource resource){
this.resource = resource;
}
#Override
public void run() {
// TODO Auto-generated method stub
synchronized(resource){
System.out.println("Before Reading Updated Value By : " +Thread.currentThread().getName() );
//We need to Take care to get the updated value, so waiting for writer thread to update value.
try {
//Release resource Lock & wait till any notification from Writer.
resource.wait();
System.out.println("Waiting is Over For : "+ Thread.currentThread().getName());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Read Updated Value
System.out.println("Updated Value of Resource Mesg :" + resource.getMesg() + " Read By :" +Thread.currentThread().getName());
}
}
}
WriterThreadTask.java
public class WriterThreadTask implements Runnable{
private Resource resource;
public WriterThreadTask(Resource resource){
this.resource = resource;
}
#Override
public void run() {
// TODO Auto-generated method stub
synchronized(resource){
System.out.println("Before Updating Resource By : " + Thread.currentThread().getName());
//Updating resource Object Message
resource.setMesg("Hi How are You !!!");
resource.notify();
//resource.notifyAll();
//Once Writer Comes Out from Synch Block, Readers will Content to read the values.
System.out.println("Task Done By Writer Thread.");
}
}
}
ThreadDemo.java
public class ThreadDemo {
public static void main(String args[]){
//Create Single Resource Object, which can act as Lock on Writer and Readers.
Resource lock = new Resource();
//Three Readers and One Writer runnable Tasks.
Runnable taskR1 = new WaitThreadTask(lock);
Runnable taskR2 = new WaitThreadTask(lock);
Runnable taskR3 = new WaitThreadTask(lock);
Runnable taskW1 = new WriterThreadTask(lock);
Thread t1 = new Thread(taskR1, "Reader1");
Thread t2 = new Thread(taskR2, "Reader2");
Thread t3 = new Thread(taskR3, "Reader3");
Thread t4 = new Thread(taskW1, "Writer1");
t1.start();
t2.start();
t3.start();
/*try{
Thread.sleep(5000);
} catch(InterruptedException e){
e.printStackTrace();
}*/
t4.start();
}
}
Code Observations :
Both notify()/notifyAll() and wait() : works only on the Lock Objects they already acquire. For example : Synchornized(ObjectA) {......// ... // ObjectB.wait() or ObjectB.notify() or ObjectB.notifyAll() ...} then It will throw IllegalMonitorStateException. Therefore care must be taken that lock must be acquired before calling any of above three methods with same lock.Even If you simply write notify() or wait() or notifyAll(), then still it will throw IllegalMonitorStateException because [It suggest lock must be acquired on this Object, again which is not the case].
Reader will only able to receive signals on which same notification is send. If wait is happening on Object which is different from Object on which notification is being send, then Readers will never get the notification and hence they will wait forever.
Readers which are registered before Writer able to send the notification, Only those readers will get it. Because if Writer sends notification first, before reader registered to Object, they will not receive the signals as Signals are already being missed : Missed Signals
Reader and Writer should acquire Lock on same Object and should invoke wait/notification signals on same Object. If the above code is modified as, instead of using resource for locks and wait and notify, If we use this. What will happen ? Well .. All readers will wait forever, Because readers registered with different Objects of WaitThreadTask and writer notify on WriterThreadTask. Therefore none of the Reader will receive notification signals, as they registered to receive signals on respective WaitThreadTask Object and not on WriterThreadTask Object.
public class ProducerConsumerInJava {
public static void main(String args[]) {
System.out.println("How to use wait and notify method in Java");
System.out.println("Solving Producer Consumper Problem");
Queue<Integer> buffer = new LinkedList<>();
int maxSize = 10;
Thread producer = new Producer(buffer, maxSize, "PRODUCER");
Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");
producer.start();
consumer.start();
}
}
class Producer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Producer(Queue<Integer> queue, int maxSize, String name){
super(name); this.queue = queue; this.maxSize = maxSize;
}
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) {
try {
System.out .println("Queue is full, " +
"Producer thread waiting for " + "consumer to take
something from queue");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Random random = new Random();
int i = random.nextInt();
System.out.println("Producing value : " + i);
queue.add(i);
queue.notifyAll();
}
}
}
}
class Consumer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Consumer(Queue<Integer> queue, int maxSize, String name){
super(name); this.queue = queue; this.maxSize = maxSize;
}
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try {
System.out .println("Queue is empty," +
"Consumer thread is waiting" +
" for producer thread to put something in queue");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("Consuming value : " + queue.remove());
queue.notifyAll();
}
}
}
}
This is an example of Consumer and Producer program.
Output of the above program after execution is written below:
How to use wait and notify
method in Java Solving Producer Consumper Problem
Queue is empty,Consumer thread is waiting for producer thread to put
something in queue
Producing value : -1692411980
Producing value : 285310787
Producing value : -1045894970
Producing value : 2140997307
Producing value : 1379699468
Producing value : 912077154
Producing value : -1635438928
Producing value : -500696499
Producing value : -1985700664
Producing value : 961945684
Queue is full, Producer thread waiting for consumer to take something from
queue Consuming value : -1692411980
Consuming value : 285310787
Consuming value : -1045894970
Consuming value : 2140997307
Consuming value : 1379699468
Consuming value : 912077154
Consuming value : -1635438928
Consuming value : -500696499
Consuming value : -1985700664
Consuming value : 961945684
Queue is empty,Consumer thread is waiting for producer thread to put
something in queue
Producing value : 118213849
So, what we can conclude is, notifyAll() or notify() will not release the lock. have a look at the output, Producing value and Consuming value are not printed alternatively i.e there are printed separately.
Hence, notify/ notifyAll will not release lock
Read more: http://javarevisited.blogspot.com/2015/07/how-to-use-wait-notify-and-notifyall-in.html#ixzz57kdToLX6
To clarify my understanding and to provide an example for all to show when the lock is released, I have added print statements to the following code after the call to notify()/NotifyAll():
class ThreadDemo {
public static void main(String[] args) {
Shared s = new Shared();
new Producer(s).start();
new Consumer(s).start();
}
}
class Shared {
private char c = '\u0000';
private boolean writeable = true;
synchronized void setSharedChar(char c) {
while (!writeable)
try {
wait();
} catch (InterruptedException e) {
}
this.c = c;
writeable = false;
notifyAll();
System.out.println("setSharedChar notify() called - still in synchronized block.");
}
synchronized char getSharedChar() {
while (writeable)
try {
wait();
} catch (InterruptedException e) {
}
writeable = true;
notifyAll();
System.out.println("getSharedChar notify() called - still in synchronized block.");
return c;
}
}
class Producer extends Thread {
private Shared s;
Producer(Shared s) {
this.s = s;
}
public void run() {
System.out.println("Starting producer thread.");
for (char ch = 'A'; ch <= 'Z'; ch++) {
System.out.println("Producer thread getting ready to create a char.");
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
}
s.setSharedChar(ch);
System.out.println(ch + " produced by producer.");
}
}
}
class Consumer extends Thread {
private Shared s;
Consumer(Shared s) {
this.s = s;
}
public void run() {
System.out.println("Starting consumer thread.");
char ch;
do {
System.out.println("Consumer thread getting ready to read a char.");
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
}
ch = s.getSharedChar();
System.out.println(ch + " consumed by consumer.");
} while (ch != 'Z');
}
}
When I ran this example enough times, there was a point where I did eventually see the output of the program show:
...
F produced by producer.
Producer thread getting ready to create a char.
getSharedChar notify() called - still in synchronized block.
F consumed by consumer.
Consumer thread getting ready to read a char.
setSharedChar notify() called - still in synchronized block.
G produced by producer.
Producer thread getting ready to create a char.
getSharedChar notify() called - still in synchronized block.
setSharedChar notify() called - still in synchronized block.
G consumed by consumer.
Since the output getSharedChar is able to appear before setSharedChar, it appears that the lock is being released immediately or not required to reenter the synchronized getSharedChar() function by the call to notifyAll(). The lock may still be in place, but if you can reenter the function without it, what is the difference?
I was able to see similar output substituting notify() for notifyAll(). This was done on Java 1.7.0_15 on a 64 bit Windows 7 system.
wait(): Virtually every object in Java posses a monitor, to enter inside any synchronized block a thread has to first acquire this monitor and then only he can enter this synchronized block. As critical section of the code is executed by a single thread at a time so it has a great impact on overall performance of the application. So in place of holding the resource(monitor) threads can be asked to leave the critical section and wait for some time. To achieve this behaviour Java has provided a wait() api directly in Object class.
So any time a thread encounter a wait() API, it drops the current monitor plus all other monitors it holds and go to waiting state linked the current object. Its important to understand that that went to the waiting state in the context of object for which thread acquired the monitor first.. In a conceptual way i explain, every object holds a container house where all waiting threads are held.
There are multiple ways a Thread can come out of this container house of Object. Lets see..
When another thread comes and rings the bell once, In Java by calling
notify() method on the same object.
When another thread comes and rings multiple time, one of the Thread
gets a chance to come out of Object’s container house. In Java we can
do this by calling notifyAll() on the same object.
If we have the reference of the Thread waiting in container house.
Calling interrupt() on the Thread object pops it out of waiting state
and brings it the exception block of the Object.
There are overloaded wait(long milliseconds) and wait(long millSec,
int nanos) methods. As the time over the Thread is eligible to come
out of waiting state and contest for Object monitor again. In case
Thread fails to acquire the monitor after timeout also then it has to
wait for notify() calls only.
notify(): If the objects container house has multiple threads in waiting state then calling notify() on the this object given chance to one the thread to proceed. But after coming out of the waiting state the thread still has to contest for the object monitor and if it succeeds in getting the monitor it continue its execution otherwise thread will come back to waiting state. So notify() also has to be called from the synchronized block. If the notify() is not called from synchronized context then it thorws IllegalMonitorStateException.
notifyAll(): Calling notifyAll() on the Object makes sure all the threads in Object container house are awakened but once awakened they have to compete with each other or any other thread wants to acquire the object monitor. Which ever thread succeeds continue its executions others have to go back to waiting state and settle in object container house. As notify(), notifyAll() should also be called in synchronized context.
Explanation Taken from http://coder2design.com/thread-communication/
Calling notify() method on an object changes the state of the waiting threads.
The notifying thread only releases the lock once it completes the execution of its synchronized code on the lock object it is going to release.
So here's how it is:
wait()
If a thread calls wait() method on an object, the thread IMMEDIATELY releases the lock of that object and goes into waiting state.
notify()
But when a thread calls notify() method on an object, the thread does not release the lock of that object immediately, if the thread have some more job to do (i.e code to execute after notify() call). If the execution of the synchronized code is completed or there are no statements after notify(), then the thread releases the lock for waken up threads from waiting state.

Two BlockingQueue - deadlock

I have a requirement to manipulate two queues atomically and am not sure what is the correct synchronization strategy: This is what I was trying:
public class transfer {
BlockingQueue firstQ;
BlockingQueue secondQ;
public moveToSecond() {
synchronized (this){
Object a = firstQ.take();
secondQ.put(a)
}
}
public moveToFirst() {
synchronized(this) {
Object a = secondQ.take();
firstQ.put(a);
}
}
}
Is this the correct pattern? In the method moveToSecond(), if firstQ is empty, the method will wait on firstQ.take(), but it still holds the lock on this object. This will prevent moveToFirst() to have a chance to execute.
I am confused about the lock release during a wait - Does the thread release all locks [both this and BlockedQUeue lock?]? What is the correct pattern to provide atomicity dealing with multiple blocking queues?
You are using the correct approach using a common mutex to synchronize between both queues. However, to avoid the situation you describe with the first queue being empty I'd suggest reimplementing moveToFirst() and moveToSecond() to use poll() rather than take(); e.g.
public void boolean moveToFirst() {
// Synchronize on simple mutex; could use a Lock here but probably
// not worth the extra dev. effort.
synchronzied(queueLock) {
boolean success;
// Will return immediately, returning null if the queue is empty.
Object o = firstQ.poll();
if (o != null) {
// Put could block if the queue is full. If you're using a bounded
// queue you could use add(Object) instead to avoid any blocking but
// you would need to handle the exception somehow.
secondQ.put(o);
success = true;
} else {
success = false;
}
}
return success;
}
Another failure condition you didn't mention is if firstQ is not empty but secondQ is full, the item will be removed from firstQ but there will be no place to put it.
So the only correct way is to use poll and offer with timeouts and code to return things to the way they were before any failure (important!), then retry after a random time until both poll and offer are successful.
This is an optimistic approach; efficient in normal operation but quite inefficient when deadlocks are frequent (average latency depends on the timeout chosen)
You should use the Lock-mechanism from java.util.concurrency, like this:
Lock lock = new ReentrantLock();
....
lock.lock();
try {
secondQ.put(firstQ.take());
} finally {
lock.unlock();
}
Do the same for firstQ.put(secondQ.take()), using the same lock object.
There is no need to use the lowlevel wait/notify methods on the Object class anymore, unless you are writing new concurrency primitives.
In your code, while the thread is blocked on BlockingQueue.take() it is holding on to the lock on this. The lock isn't released until either the code leaves the synchronized block or this.wait() is called.
Here I assume that moveToFirst() and moveToSecond() should block, and that your class controls all access to the queues.
private final BlockingQueue<Object> firstQ = new LinkedBlockingQueue();
private final Semaphore firstSignal = new Semaphore(0);
private final BlockingQueue<Object> secondQ = LinkedBlockingQueue();
private final Semaphore secondSignal = new Semaphore(0);
private final Object monitor = new Object();
public void moveToSecond() {
int moved = 0;
while (moved == 0) {
// bock until someone adds to the queue
firstSignal.aquire();
// attempt to move an item from one queue to another atomically
synchronized (monitor) {
moved = firstQ.drainTo(secondQ, 1);
}
}
}
public void putInFirst(Object object) {
firstQ.put(object);
// notify any blocking threads that the queue has an item
firstSignal.release();
}
You would have similar code for moveToFirst() and putInSecond(). The while is only needed if some other code might remove items from the queue. If you want the method that removes on the queue to wait for pending moves, it should aquire a permit from the semaphore, and the semaphore should be created as a fair Semaphore, so the first thread to call aquire will get released first:
firstSignal = new Semaphore(0, true);
If you don't want moveToFirst() to block you have a few options
Have the method do do its work in a Runnable sent to an Executor
Pass a timeout to moveToFirst() and use BlockingQueue.poll(int, TimeUnit)
Use BlockingQueue.drainTo(secondQ, 1) and modify moveToFirst() to return a boolean to indicate if it was successful.
For the above three options, you wouldn't need the semaphore.
Finally, I question the need to make the move atomic. If multiple threads are adding or removing from the queues, then an observing queue wouldn't be able to tell whether moveToFirst() was atomic.

Categories