I have written the following test code in Java using ReentrantReadWriteLock to understand the difference between fair and non-fair mode. However, I see in both modes the result and output is always the same. It seems it's always working in fair mode. Can anybody explain in which case fair and non-fair mode will result in different behaviors?
package lockTest;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MyLockTest {
static private ReadWriteLock myLock = new ReentrantReadWriteLock(false);
public class Reader extends Thread {
int val_;
public Reader(int val) {
val_ = val;
}
public void run() {
if (val_ > 0) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
myLock.readLock().lock();
System.out.println(Thread.currentThread().getName() + ": Reader inside critical section - val: " + val_ + "-----");
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myLock.readLock().unlock();
}
}
public class Writer extends Thread {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myLock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + ": Writer inside critical section *****");
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myLock.writeLock().unlock();
}
}
public static void main(String[] args) {
MyLockTest test1 = new MyLockTest();
MyLockTest.Reader reader1 = test1.new Reader(0);
MyLockTest.Writer writer1 = test1.new Writer();
MyLockTest.Reader reader2 = test1.new Reader(1);
reader2.start();
writer1.start();
reader1.start();
}
}
The output is always:
Thread-0: Reader inside critical section - val: 0-----
Thread-1: Writer inside critical section *****
Thread-2: Reader inside critical section - val: 1-----
The output above is what I expect to see when I change Lock creation to fair mode:
static private ReadWriteLock myLock = new ReentrantReadWriteLock(true);
For non-fair mode I would expect to see the following output:
Thread-0: Reader inside critical section - val: 0-----
Thread-2: Reader inside critical section - val: 1-----
Thread-1: Writer inside critical section *****
Using "fair" versus "non-fair" mode affects how the lock is assigned to threads in case of contention.
From the Javadoc for ReentrantReadWriteLock: using the "non-fair" mode, the order of entry to the read and write lock is unspecified, while using the "fair" mode, threads contend for entry using an approximately arrival-order policy.
We can see how using fair/non-fair affects program execution by having some thread contend over the same lock; see the program below.
Running the sample code, a ReentrantWriteLock is contended by different threads; after 1000 lock operations, we dump how many times each thread acquired the lock.
In case USE_FAIR=false is used, counts are random, and a possible output is:
Thread thread-B finished, count=920
Thread thread-A finished, count=79
Thread thread-D finished, count=0
Thread thread-C finished, count=0
in case USE_FAIR=true is used, the output is always like
Thread thread-D finished, count=249
Thread thread-A finished, count=250
Thread thread-C finished, count=250
Thread thread-B finished, count=250
Sample code
package sample1;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class UseLock {
public static void main(String[] args) {
UseLock o = new UseLock();
o.go();
}
private void go() {
TotalPermits tp = new TotalPermits();
tp.lock.writeLock().lock();
Contender a = new Contender(tp, "thread-A");
Contender b = new Contender(tp, "thread-B");
Contender c = new Contender(tp, "thread-C");
Contender d = new Contender(tp, "thread-D");
a.start();
b.start();
c.start();
d.start();
tp.lock.writeLock().unlock();
}
}
class TotalPermits {
private static final boolean USE_FAIR = true;
private int count = 1_000;
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(USE_FAIR);
public boolean get() {
try {
lock.writeLock().lock();
try {
Thread.sleep(1);
} catch (InterruptedException e) { }
return --count>0;
} finally {
lock.writeLock().unlock();
}
}
}
class Contender extends Thread {
private int count = 0;
final String name;
final TotalPermits tp;
Contender(TotalPermits tp, String name) {
this.tp = tp;
this.name = name;
}
#Override
public void run() {
while ( tp.get() ) {
count++;
}
System.out.printf("Thread %s finished, count=%d%n", name, count);
}
}
Note:
The sample code above uses a "write" lock, which can only be held by one thread at a time. So we can use that to divide N permits across the contenders. On the other hand, the "read" lock can be held by multiple threads, as long as none is holding the write lock.
Related
So I'm trying to create a client/server program. I want to know when my client disconnects of his own accord, so I've setup a heartbeat system. Every 6 seconds my client sends a ping to my server, if the client doesn't send a ping for a total of 30 seconds the client is considered disconnected and removed from the current connections list (for which I plan to implement a GUI). Or at least, that's the plan.
ConnectionManager.java
public class ConnectionManager implements Runnable{
static Socket connection;
private ArrayList<Thread> allConnections;
private ArrayList<Connection> allConnectionList;
private ServerSocket server;
private int id = 0;
public ConnectionManager() {
allConnections = new ArrayList<Thread>();
allConnectionList = new ArrayList<Connection>();
}
#Override
public void run() {
try {
server = new ServerSocket(5555);
System.out.println("Server is running!");
while(true) {
connection = server.accept();
Connection a = new Connection(connection, id);
Runnable runnable = a;
allConnectionList.add(a);
allConnections.add(new Thread(runnable));
allConnections.get(allConnections.size() - 1).start();
id++;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void removeConnection(int id) {
allConnections.remove(id);
allConnectionList.remove(id);
}
Connection.java
public class Connection implements Runnable {
private Socket a;
public boolean amIActive;
private int id;
public Connection(Socket a, int id) {
amIActive = true;
this.a = a;
this.id = id;
}
public void onConnect() {
try {
String TimeStamp = new java.util.Date().toString();
String formattedAddress = a.getInetAddress().toString().replace("/", "");
System.out.println("Received connection from: " + formattedAddress + " at " + TimeStamp);
Runnable runnable = new ConnectionListener(this);
Thread connectionThread = new Thread(runnable);
connectionThread.start();
String returnCode = "Server repsonded to " + a.getInetAddress().toString().replace("/", "") + " at "+ TimeStamp + (char) 13;
BufferedOutputStream os = new BufferedOutputStream(a.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(os, "US-ASCII");
osw.write(returnCode);
osw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
onConnect();
System.out.println("We got this far!");
while(amIActive) {
whileTrue();
}
System.out.println("This code never gets run because we get stuck in the while loop above");
Main.b.removeConnection(id);
System.out.println("Connection was closed from " + a.getInetAddress());
}
public void setOffline(boolean state) {
this.amIActive = state;
}
public void whileTrue() {
}
public Socket getSocket() {
return a;
}
ConnectionListener.java
public class ConnectionListener implements Runnable{
public Connection myConnection;
public boolean receivedHeartbeat;
public int missedHeartbeats = 0;
public ConnectionListener(Connection a) {
this.myConnection = a;
}
#Override
public void run() {
Runnable runnable = new Heartbeat(this);
Thread thread = new Thread(runnable);
thread.start();
while(myConnection.amIActive) {
try {
BufferedInputStream is;
is = new BufferedInputStream(myConnection.getSocket().getInputStream());
InputStreamReader isr = new InputStreamReader(is);
StringBuffer process = new StringBuffer();
int character;
while((character = isr.read()) != 13) { //GETTING STUCK HERE BECAUSE STUPID.
if(character == -1) {
myConnection.setOffline(true);
} else {
process.append((char)character);
}
}
handleInput(process);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void handleInput(StringBuffer process) {
String messageSent = process.toString();
if(messageSent.equals("Ping!")) {
receivedHeartbeat = true;
}
}
Heartbeat.java
public class Heartbeat implements Runnable{
private ConnectionListener b;
public Heartbeat(ConnectionListener a) {
b = a;
}
#Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
if(b.missedHeartbeats > 5) {
b.myConnection.amIActive = false;
System.out.println("Setting amIActiveToFalse!");
}
if(b.receivedHeartbeat) {
b.receivedHeartbeat = false;
} else {
b.missedHeartbeats++;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
My console is spammed with System.out.println("Setting amIActiveToFalse!"); from Heartbeat.java. But the while loop in Connection.java keeps running. I believe this might be something to do with my threading, but I can't figure it out.
When you have a non-volatile variable, there is no guarentee of visability of a change in one thread to another. In particular, if the JVM detects that a thread doesn't alter a boolean it can inline it, meaning you will never see the value change.
The simple solution is to make the boolean volatile and it will not be inlined and one thread will see when another changes it.
For more details http://vanillajava.blogspot.com/2012/01/demonstrating-when-volatile-is-required.html
The trivial answer to this is: make the variable volatile.
Without this, it is allowed for the thread changing the value to basically keep its updates in cache, committing them to main memory some time later.
This allows threaded code to run much faster, since it can keep its variables in cache rather than having to fetch from main memory. However, the consequence of this is that other threads don't see the update.
Making the variable volatile prevents this from happening: a thread always reads the value from main memory, and writes are immediately committed.
I say that this is the trivial answer because it doesn't necessarily fix all of your problems. There may also be an atomicity issue: in between one thread reading the variable and writing it again, another thread might sneak in and change its value, which may or may not put the first thread into an undefined state from the perspective of its invariants.
Specifically:
if(b.receivedHeartbeat) { b.receivedHeartbeat = false;
It is possible that some other thread can change b.receivedHeartbeat to false after this thread evaluates it to true, so this iteration is erroneously counted as a "non-missed" heartbeat.
This can be fixed by making the variable a (non-volatile) AtomicBoolean, on which there is an atomic compare-and-set method, which avoids such race conditions.
Java Concurrency In Practice is a great reference on these issues, I wholeheartedly recommend it. Look for the topics "visibility" and "atomicity".
Also read the advanced chapter on the Java Memory Model. That made me doubt myself at first, but made me a much stronger programmer after I digested it.
There are a couple issues I saw while debugging the code you posted, but I was able to successfully get the heartbeat functionality working.
In the Connection Listener class I don't think the if statement with .equals("Ping!") will match, because of the newline character at the end of each line.
In the Connection Listener class I would probably put the socket's Input Stream at the top of the loop not inside the loop. (I don't think this will break it but it's probably nicer this way)
ConnectionListener Updates:
public void run() {
Runnable runnable = new Heartbeat(this);
Thread thread = new Thread(runnable);
thread.start();
BufferedReader br = null;
try {
//is = new BufferedInputStream(myConnection.getSocket().getInputStream());
br = new BufferedReader(new InputStreamReader(myConnection.getSocket().getInputStream()));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(myConnection.amIActive) {
try {
String processLine = br.readLine();
System.out.println("handleInput:" + processLine);
handleInput(processLine);
} catch (Exception e) {
System.out.println("Exception!");
e.printStackTrace();
}
}
}
public void handleInput(String messageSent) {
if(messageSent.startsWith("Ping!")) { //Need to use startsWith, or add newline character
receivedHeartbeat = true;
System.out.println("receivedHeartbeat!");
}
}
Also, in your Heartbeat class make sure you reset the missedHeartbeats counter to 0 on true:
if(b.receivedHeartbeat) {
b.receivedHeartbeat = false;
b.missedHeartbeats = 0;
} else {
b.missedHeartbeats++;
}
Problem: While trying to retrieve values inside a recursive block in a phased manner, the execution gets hung.
Description: CountDownLatch & Object.wait are used to achieve the phased manner access of value inside the recursive block. But, the program hangs with following output:
2 < 16
3 < 16
4 < 16
5 < 16
Current total: 5
Inside of wait
Inside of wait
Program:
import java.util.concurrent.*;
public class RecursiveTotalFinder {
private static CountDownLatch latch1;
private static CountDownLatch latch2;
private static CountDownLatch latch3;
public static void main(String... args) {
latch1 = new CountDownLatch(1);
latch2 = new CountDownLatch(1);
latch3 = new CountDownLatch(1);
//Create object
TotalFinder tf = new TotalFinder(latch1,latch2,latch3);
//Start the thread
tf.start();
//Wait for results from TotalFinder
try {
latch1.await();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
//Print the result after 5th iteration
System.out.println("Current total: "+tf.getCurrentTotal());
tf.releaseWaitLock();
tf.resetWaitLock();
//Wait for results again
try {
latch2.await();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
//Print the result after 10th iteration
System.out.println("Current total: "+tf.getCurrentTotal());
tf.releaseWaitLock();
tf.resetWaitLock();
//Wait for results again
try {
latch3.await();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
//Print the result after 15th iteration
System.out.println("Current total: "+tf.getCurrentTotal());
tf.releaseWaitLock();
tf.resetWaitLock();
}
}
class TotalFinder extends Thread{
CountDownLatch tfLatch1;
CountDownLatch tfLatch2;
CountDownLatch tfLatch3;
private static int count = 1;
private static final class Lock { }
private final Object lock = new Lock();
private boolean gotSignalFromMaster = false;
public TotalFinder(CountDownLatch latch1, CountDownLatch latch2,
CountDownLatch latch3) {
tfLatch1 = latch1;
tfLatch2 = latch2;
tfLatch3 = latch3;
}
public void run() {
findTotal(16);
}
//Find total
synchronized void findTotal(int cnt) {
if(count%5==0) {
if(count==5)
tfLatch1.countDown();
if(count==10)
tfLatch2.countDown();
if(count==15)
tfLatch3.countDown();
//Sleep for sometime
try {
Thread.sleep(3000);
} catch(InterruptedException ie) {
ie.printStackTrace();
}
//Wait till current total is printed
synchronized(lock) {
while(gotSignalFromMaster==false) {
try {
System.out.println(" Inside of wait");
lock.wait();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
}
System.out.println("Came outside of wait");
}
}
count +=1;
if(count < cnt) {
System.out.println(count +" < "+cnt);
findTotal(cnt);
}
}
//Return the count value
public int getCurrentTotal() {
return count;
}
//Release lock
public void releaseWaitLock() {
//Sleep for sometime
try {
Thread.sleep(5000);
} catch(InterruptedException ie) {
ie.printStackTrace();
}
synchronized(lock) {
gotSignalFromMaster=true;
lock.notifyAll();
}
}
//Reset wait lock
public void resetWaitLock() {
gotSignalFromMaster = false;
}
}
Analysis:
In my initial analysis it looks like the wait is happening recursively eventhough notifyAll is invoked from the main program.
Help:
Why free lock using notfiyAll after a CountDownLatch didn't take effect? Need someone's help in understanding what exactly is happening in this program.
The main message about wait and notify that I got from JCIP was that I'd probably use them wrongly, so better to avoid using them directly unless strictly necessary. As such, I think that you should reconsider the use of these methods.
In this case, I think that you can do it more elegantly using SynchronousQueue. Perhaps something like this might work:
import java.util.concurrent.*;
public class RecursiveTotalFinder {
public static void main(String... args) throws InterruptedException {
SynchronousQueue<Integer> syncQueue = new SynchronousQueue<>();
//Create object
TotalFinder tf = new TotalFinder(syncQueue, 5);
//Start the thread
tf.start();
for (int i = 0; i < 3; ++i) {
System.out.println("Current total: " + syncQueue.take());
}
}
}
class TotalFinder extends Thread{
private final SynchronousQueue<Integer> syncQueue;
private final int syncEvery;
private int count;
public TotalFinder(SynchronousQueue<Integer> syncQueue,
int syncEvery) {
this.syncQueue = syncQueue;
this.syncEvery = syncEvery;
}
public void run() {
try {
findTotal(16);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
//Find total
void findTotal(int cnt) throws InterruptedException {
if((count > 0) && (count%syncEvery==0)) {
syncQueue.put(count);
}
count +=1;
if(count < cnt) {
System.out.println(count +" < "+cnt);
findTotal(cnt);
}
}
}
As to why your original approach doesn't work, it's because the main thread sets gotSignalFromMaster to true and then immediately back to false, and this happens before the other thread is able to check its value. If you stick a bit of a sleep into the resetWaitLock, it proceeds beyond the point where it currently hangs; however, it then hangs at the end instead of terminating.
Note that having to use Thread.sleep to wait for another thread to change some state is a poor approach - not least because it makes your program really slow. Using synchronization utilities leads to faster and much easier-to-reason-about program.
I research ReentrantReadWriteLock.
I write simple code for test(I know that use Thread.sleep() can not guarantee predictable result but I think that I am lucky:)):
public class RWLock {
private static String val = "old";
private static ReadWriteLock lock = new ReentrantReadWriteLock();
private static long time = System.currentTimeMillis();
public void read() {
try {
lock.readLock().lock();
System.out.println("read " + val +" - "+(System.currentTimeMillis()-time));
Thread.sleep(300);
} catch (InterruptedException e) {
} finally {
lock.readLock().unlock();
}
}
public void write() {
try {
lock.writeLock().lock();
val = "new";
System.out.println("write " + val+" - "+(System.currentTimeMillis()-time));
Thread.sleep(10000);
} catch (InterruptedException e) {
} finally {
lock.writeLock().unlock();
}
}
}
class Tester {
public static void main(String[] args) throws InterruptedException {
new MyThreadRead().start();
Thread.sleep(400);
new MyThreadWrite().start();
}
}
class MyThreadRead extends Thread {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
new RWLock().read();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
}
class MyThreadWrite extends Thread {
#Override
public void run() {
new RWLock().write();
}
}
output:
read old - 0
write new - 401
read new - 10401
read new - 10902
read new - 11402
read new - 11902
read new - 12402
read new - 12902
read new - 13402
read new - 13902
read new - 14402
10401 - 401 == 10000
10000 it is time of writing.
As I understood second read thread cannot finish before writing. Thus writing and second reading performs in parallel. It is not predictable behaviour for me.
What do you think about it?
Maybe you have more sleep() calls than you realize. The sleep calls in MyThreadRead#run() and in RWLock()#read() add up to 500 ms. So here's what's happening.
At T=0, the reader thread grabs the read lock and sleeps for 300ms.
At T=300, the reader releases the lock, and then sleeps for another 200ms.
At T=400, the writer grabs the write lock and sleeps for ten seconds,
At T=500, the reader tries to grab the read lock, but it is blocked by the writer.
At T=10400, the writer gives up the lock, and then the reader gets to go round
its loop nine more times.
P.S.: Move your lock() calls out of the try/finally statements. E.g.,
...lock()
try {
...
} finally {
...unlock();
}
That way, if the lock() call throws an exception, the unlock() will not be called.
I want to write program using multithreading wait and notify methods in Java.
This program has a stack (max-length = 5). Producer generate number forever and put it in the stack, and consumer pick it from stack.
When stack is full producer must wait and when stack is empty consumers must wait.
The problem is that it runs just once, I mean once it produce 5 number it stops but i put run methods in while(true) block to run nonstop able but it doesn't.
Here is what i tried so far.
Producer class:
package trail;
import java.util.Random;
import java.util.Stack;
public class Thread1 implements Runnable {
int result;
Random rand = new Random();
Stack<Integer> A = new Stack<>();
public Thread1(Stack<Integer> A) {
this.A = A;
}
public synchronized void produce()
{
while (A.size() >= 5) {
System.out.println("List is Full");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = rand.nextInt(10);
System.out.println(result + " produced ");
A.push(result);
System.out.println(A);
this.notify();
}
#Override
public void run() {
System.out.println("Producer get started");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
produce();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And the consumer:
package trail;
import java.util.Stack;
public class Thread2 implements Runnable {
Stack<Integer> A = new Stack<>();
public Thread2(Stack<Integer> A) {
this.A = A;
}
public synchronized void consume() {
while (A.isEmpty()) {
System.err.println("List is empty" + A + A.size());
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.err.println(A.pop() + " Consumed " + A);
this.notify();
}
#Override
public void run() {
System.out.println("New consumer get started");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
consume();
}
}
}
and here is the main method:
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
Thread1 thread1 = new Thread1(stack);// p
Thread2 thread2 = new Thread2(stack);// c
Thread A = new Thread(thread1);
Thread B = new Thread(thread2);
Thread C = new Thread(thread2);
A.start();
B.start();
C.start();
}
I think it will be better for understanding and dealing with synchronisation in general if you try to separate three things which are currently mixed:
Task which is going to do the actual job. Names for classes Thread1 & Thread2 are misleading. They are not Thread objects, but they are actually jobs or tasks implementing Runnable interface you are giving to Thread objects.
Thread object itself which you are creating in main
Shared object which encapsulates synchronised operations/logic on a queue, a stack etc. This object will be shared between tasks. And inside this shared object you will take care of add/remove operations (either with synchronized blocks or synchronized methods). Currently (as it was pointed out already), synchronization is done on a task itself (i.e. each task waits and notifies on its own lock and nothing happens). When you separate concerns, i.e. let one class do one thing properly it will eventually become clear where is the problem.
Your consumer and you producer are synchronized on different objects and do not block each other. If this works, I daresay it's accidental.
Read up on java.util.concurrent.BlockingQueue and java.util.concurrent.ArrayBlockingQueue. These provide you with more modern and easier way to implement this pattern.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
You should synchronize on the stack instead of putting it at the method level try this code.
Also don't initalize the stack in your thread classes anyways you are passing them in the constructor from the main class, so no need of that.
Always try to avoid mark any method with synchronized keyword instead of that try to put critical section of code in the synchronized block because the more size of your synchronized area more it will impact on performance.
So, always put only that code into synchronized block that need thread safety.
Producer Code :
public void produce() {
synchronized (A) {
while (A.size() >= 5) {
System.out.println("List is Full");
try {
A.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = rand.nextInt(10);
System.out.println(result + " produced ");
A.push(result);
System.out.println("stack ---"+A);
A.notifyAll();
}
}
Consumer Code :
public void consume() {
synchronized (A) {
while (A.isEmpty()) {
System.err.println("List is empty" + A + A.size());
try {
System.err.println("wait");
A.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.err.println(A.pop() + " Consumed " + A);
A.notifyAll();
}
}
Try this:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CircularArrayQueue<T> {
private volatile Lock rwLock = new ReentrantLock();
private volatile Condition emptyCond = rwLock.newCondition();
private volatile Condition fullCond = rwLock.newCondition();
private final int size;
private final Object[] buffer;
private volatile int front;
private volatile int rare;
/**
* #param size
*/
public CircularArrayQueue(int size) {
this.size = size;
this.buffer = new Object[size];
this.front = -1;
this.rare = -1;
}
public boolean isEmpty(){
return front == -1;
}
public boolean isFull(){
return (front == 0 && rare == size-1) || (front == rare + 1);
}
public void enqueue(T item){
try {
// get a write lock
rwLock.lock();
// if the Q is full, wait the write lock
if(isFull())
fullCond.await();
if(rare == -1){
rare = 0;
front = 0;
} else if(rare == size - 1){
rare = 0;
} else {
rare ++;
}
buffer[rare] = item;
//System.out.println("Added\t: " + item);
// notify the reader
emptyCond.signal();
} catch(InterruptedException e){
e.printStackTrace();
} finally {
// unlock the write lock
rwLock.unlock();
}
}
public T dequeue(){
T item = null;
try{
// get the read lock
rwLock.lock();
// if the Q is empty, wait the read lock
if(isEmpty())
emptyCond.await();
item = (T)buffer[front];
//System.out.println("Deleted\t: " + item);
if(front == rare){
front = rare = -1;
} else if(front == size - 1){
front = 0;
} else {
front ++;
}
// notify the writer
fullCond.signal();
} catch (InterruptedException e){
e.printStackTrace();
} finally{
// unlock read lock
rwLock.unlock();
}
return item;
}
}
You can use Java's awesome java.util.concurrent package and its classes.
You can easily implement the producer consumer problem using the
BlockingQueue. A BlockingQueue already supports operations that wait
for the queue to become non-empty when retrieving an element, and wait
for space to become available in the queue when storing an element.
Without BlockingQueue, every time we put data to queue at the producer
side, we need to check if queue is full, and if full, wait for some
time, check again and continue. Similarly on the consumer side, we
would have to check if queue is empty, and if empty, wait for some
time, check again and continue. However with BlockingQueue we don’t
have to write any extra logic than to just add data from Producer and
poll data from Consumer.
Read more From:
http://javawithswaranga.blogspot.in/2012/05/solving-producer-consumer-problem-in.html
http://www.javajee.com/producer-consumer-problem-in-java-using-blockingqueue
use BlockingQueue,LinkedBlockingQueue this was really simple.
http://developer.android.com/reference/java/util/concurrent/BlockingQueue.html
package javaapplication;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ProducerConsumer {
public static Object lock = new Object();
public static Stack stack = new Stack();
public static void main(String[] args) {
Thread producer = new Thread(new Runnable() {
int i = 0;
#Override
public void run() {
do {
synchronized (lock) {
while (stack.size() >= 5) {
try {
lock.wait();
} catch (InterruptedException e) {
}
}
stack.push(++i);
if (stack.size() >= 5) {
System.out.println("Released lock by producer");
lock.notify();
}
}
} while (true);
}
});
Thread consumer = new Thread(new Runnable() {
#Override
public void run() {
do {
synchronized (lock) {
while (stack.empty()) {
try {
lock.wait();
} catch (InterruptedException ex) {
Logger.getLogger(ProdCons1.class.getName()).log(Level.SEVERE, null, ex);
}
}
while(!stack.isEmpty()){
System.out.println("stack : " + stack.pop());
}
lock.notifyAll();
}
} while (true);
}
});
producer.start();
consumer.start();
}
}
Have a look at this code example:
import java.util.concurrent.*;
import java.util.Random;
public class ProducerConsumerMulti {
public static void main(String args[]){
BlockingQueue<Integer> sharedQueue = new LinkedBlockingQueue<Integer>();
Thread prodThread = new Thread(new Producer(sharedQueue,1));
Thread consThread1 = new Thread(new Consumer(sharedQueue,1));
Thread consThread2 = new Thread(new Consumer(sharedQueue,2));
prodThread.start();
consThread1.start();
consThread2.start();
}
}
class Producer implements Runnable {
private final BlockingQueue<Integer> sharedQueue;
private int threadNo;
private Random rng;
public Producer(BlockingQueue<Integer> sharedQueue,int threadNo) {
this.threadNo = threadNo;
this.sharedQueue = sharedQueue;
this.rng = new Random();
}
#Override
public void run() {
while(true){
try {
int number = rng.nextInt(100);
System.out.println("Produced:" + number + ":by thread:"+ threadNo);
sharedQueue.put(number);
Thread.sleep(100);
} catch (Exception err) {
err.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
private final BlockingQueue<Integer> sharedQueue;
private int threadNo;
public Consumer (BlockingQueue<Integer> sharedQueue,int threadNo) {
this.sharedQueue = sharedQueue;
this.threadNo = threadNo;
}
#Override
public void run() {
while(true){
try {
int num = sharedQueue.take();
System.out.println("Consumed: "+ num + ":by thread:"+threadNo);
Thread.sleep(100);
} catch (Exception err) {
err.printStackTrace();
}
}
}
}
Notes:
Started one Producer and two Consumers as per your problem statement
Producer will produce random numbers between 0 to 100 in infinite loop
Consumer will consume these numbers in infinite loop
Both Producer and Consumer share lock free and Thread safe LinkedBlockingQueue which is Thread safe. You can remove wait() and notify() methods if you use these advanced concurrent constructs.
Seems like you skipped something about wait(), notify() and synchronized.
See this example, it should help you.
I am just trying to model a simple readers / writers scenario.
Here is the code:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReadersWriters implements Solution {
private final static Lock readerLock = new ReentrantLock();
private final static Lock writerLock = new ReentrantLock();
private final static Condition noReader = readerLock.newCondition();
private static CountDownLatch countDown;
private static volatile int readerCount=0;
public static class Reader implements Runnable {
private static int count=1;
private int id = count++;
#Override
public void run() {
int readCount = (int) (Math.random()*20);
while (readCount > 0) {
readCount--;
writerLock.lock();
try {
readerLock.lock();
try {
readerCount++;
} finally {
readerLock.unlock();
}
} finally {
writerLock.unlock();
}
System.out.println("Reader "+id+" reading ("+readerCount+" readers)");
try {
Thread.sleep((long) (Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Reader "+id+" done");
readerLock.lock();
try {
readerCount--;
noReader.signalAll();
} finally {
readerLock.unlock();
}
try {
Thread.sleep((long) (Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
countDown.countDown();
}
}
public static class Writer implements Runnable {
private static int count=1;
private int id = count++;
#Override
public void run() {
int writeCount = (int) (Math.random()*20);
while (writeCount>0) {
writeCount--;
writerLock.lock();
try {
readerLock.lock();
try {
while (readerCount>0) {
noReader.await();
}
System.out.println("Writer "+id+" writing");
try {
Thread.sleep((long) (Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Writer "+id+" done");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
readerLock.unlock();
}
} finally {
writerLock.unlock();
}
try {
Thread.sleep((long) (Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
countDown.countDown();
}
}
public static void main(String []args) {
Executor exec = Executors.newCachedThreadPool();
int numReaders = 10;
int numWriters = 4;
countDown = new CountDownLatch(numReaders+numWriters);
for (int i=0; i<numReaders; i++) {
exec.execute(new Reader());
}
for (int i=0; i<numWriters; i++) {
exec.execute(new Writer());
}
try {
countDown.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I know I could also use ReadWriteLock, but that's not the point...
My problem is that in the log, I see things like this:
Writer 4 writing
Writer 4 done
Reader 9 reading (1 readers)
Reader 8 reading (3 readers)
Reader 5 reading (2 readers)
Reader 8 done
Reader 5 done
Reader 9 done
Writer 3 writing
Writer 3 done
And I really don't see how this could happen... Is it just console prints that are getting mixed up or I am really missing something here?
I believe your problem is about these few lines right?
Reader 9 reading (1 readers)
Reader 8 reading (3 readers)
Reader 5 reading (2 readers)
which you expect it to be 1,2 and then 3 readers.
In brief, the problem is because your printing is not part of the synchronization block.
To give an example of possible cause base on your code, here it is:
writerLock.lock();
try {
readerLock.lock();
try {
readerCount++;
} finally {
readerLock.unlock();
}
} finally {
writerLock.unlock();
}
System.out.println("Reader "+id+" reading ("+readerCount+" readers)");
for the above piece of code, in brief, update of readerCount is guarded by writerLock. However it is possible that:
READER8 READER5
(readerCount = 1 at this point)
lock writerLock
readerCount++ (=2)
unlock writerLock
lock writerLock
update readerCount to 3
unlock writerLock
sysout of readerCount (3)
lock writerLock
readerCount-- (=2)
sysout of readerCount (2)
unlock writerLock
lock writerLock
readerCount-- (=1)
unlock writerLock
Not hard to imagine why the number looks strange.
Put the system out statement in the locked scope, just after readerCount++, will give u result expected.
Your System.out.println calls in the Reader aren't synchronised. What, exactly, worries you here?