Sunday, August 4, 2013
Synchronization is built around an internal intity known as intrinsic lock or monitor lock. It helps in achieving an exclusive access to an object's state and establishes a happens-before relationship. In java every object has an intrinsic lock associated with it. A thread can have exclusive access only when it has acquired an intrinsic lock on that object. When it has completed its operation, it must release the lock. No other threads can acquire lock on that object in the meantime. If any other threads try to do that it will be blocked. In Java, a thread acquires an intrinsic lock as soon as it call a synchronized method or block. The lock is released when the method returns or block ends. Here we will use this technique to solve the famous Producer-Consumer example.
About Producer-Consumer Example : This is a famous problem where a producer will produce messages in a buffer and the consumer will consume those messages from buffer. Here buffer is the shared resource. There is no problem if it is unbounded buffer, but in practical situations its always bounded (Here also we will show with bounded buffer). If the buffer is empty, then the consumer must wait for producer to produce; and if buffer is full, producer must wait for consumer to consume.
       In our example, we will have a shared queue where the data will be produced. After producing , producer thread will go to sleep for a random time. Similarly for consumer , after it consumes a data it will go to sleep for random time. Producer thread will produce data and call produce() method while consumer thread will call consume() method and these two methods are synchronized. Whenever buffer is empty or full the concerned thread will wait by calling wait() method, and as soon as there is a change in status of buffer it will be informed using notifyAll(). So we can also say that we are trying to solve this problem using wait and notify.
--------------------------------------------------------------------------------------------------------------------------
Java Source Code
--------------------------------------------------------------------------------------------------------------------------
/* Code for the Shared-Object */
package intrinsic;

import java.util.LinkedList;
import java.util.Queue;

public class SharedObject {
     //buffer to store data
     private Queue<Integer> queue=new LinkedList<>();
     private final int SIZE;  //maximum size of buffer
     
     public SharedObject(int size){
    SIZE=size;
     }
     
     public synchronized void produce(int i){
     while(queue.size()==SIZE){
    System.out.println("Queue full."+Thread.currentThread().getName()+" is waiting to produce");
    try {
wait();  //wait if buffer is full
} catch (InterruptedException e) {
e.printStackTrace();
}
    }
     queue.add(i);  //storing the data
 System.out.println("Produced : "+i);
     notifyAll();  //notify consumer that status has changed
     }
     
     public synchronized int consume(){
     while(queue.size()==0){
    System.out.println("Queue empty."+Thread.currentThread().getName()+" is waiting to consume");
    try {
wait();  //wait if buffer is empty
} catch (InterruptedException e) {
e.printStackTrace();
}
    }
     notifyAll();  //notify producer that status has changed
     return queue.remove();  //consume the data
     }
}

/* Code for Producer thread */
package intrinsic;

import java.util.Random;

public class Producer implements Runnable {
private SharedObject so;
public Producer(SharedObject so){
this.so=so;
}
@Override
public void run() {
Random r=new Random();
for(int i=1;i<=10;i++){
so.produce(i);
try {
Thread.sleep(r.nextInt(5000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

/* Code for Consumer thread */
package intrinsic;

import java.util.Random;

public class Consumer implements Runnable {
private SharedObject so;
public Consumer(SharedObject so){
this.so=so;
}
@Override
public void run() {
Random r=new Random();
int i=0;
while((i=so.consume())<10){
System.out.println("Consumed : "+i);
try {
Thread.sleep(r.nextInt(5000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
                System.out.println("Consumed : "+i);
}
}

/* Code to run this example */
package intrinsic;

public class Demo {

public static void main(String[] args) {
SharedObject so=new SharedObject(2);
(new Thread(new Producer(so), "Producer")).start();
(new Thread(new Consumer(so), "Consumer")).start();
}
}
--------------------------------------------------------------------------------------------------------------------------
Output
--------------------------------------------------------------------------------------------------------------------------
Produced : 1
Consumed : 1
Queue empty.Consumer is waiting to consume
Produced : 2
Consumed : 2
Produced : 3
Consumed : 3
Produced : 4
Produced : 5
Queue full.Producer is waiting to produce
Consumed : 4
Produced : 6
Queue full.Producer is waiting to produce
Consumed : 5
Produced : 7
Queue full.Producer is waiting to produce
Consumed : 6
Produced : 8
Queue full.Producer is waiting to produce
Consumed : 7
Produced : 9
Queue full.Producer is waiting to produce
Consumed : 8
Produced : 10
Consumed : 9
Consumed : 10
--------------------------------------------------------------------------------------------------------------------------
Download Links
--------------------------------------------------------------------------------------------------------------------------

0 comments:

Post a Comment

Total Pageviews

Followers


Labels

Popular Posts

free counters