Though the below is well known topic I want Your ideas please.
I had written a small program as below: All the producers are queued up and also the consumers. I couldn't understand why it is so. What are the scenarios where it can block completely.
Let us consider Producers/consumers are waiting for lock on array and what making consumers /producers to exit out the synchronized block. I mean it has to move atleast slowly but deadlock must not happen. I believe.
Here I have 2 questions:
1. What are the scenarios that deadlock is happening.
2. How to understand what is happening under the hood. I mean how to debug.
public class ProducerConsumer implements Runnable {
boolean producer = false;
private volatile int i = 0;
int[] array = new int[10];
public static String getThreadName() {
return Thread.currentThread().getName();
}
public void producer() {
try {
synchronized (array) {
while (i > 9) {
System.out.println("Producer of " + getThreadName()
+ " is waiting i " + i);
array.wait();
System.out.println("Producer of " + getThreadName()
+ " came out of sleep i " + i);
}
System.out.println("Producer of " + getThreadName()
+ " in synchronized block i" + i);
array[i] = generateRandom();
System.out.println("Producer of " + getThreadName()
+ " inserted in array " + array[i] + " index " + i);
i++;
array.notifyAll();
}
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("Producer of " + getThreadName()
+ " interrupted " + e);
}
}
public void consumer() {
try {
synchronized (array) {
while (i < 0) {
System.out.println("Consumer of " + getThreadName()
+ " is waiting i " + i);
array.wait();
System.out.println("Consumer of " + getThreadName()
+ " came out of sleep i " + i);
}
System.out.println("Consumer of " + getThreadName()
+ " in synchronized block extracted value " + array[i]
+ " of index " + i);
i--;
array.notifyAll();
}
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("Consumer of " + getThreadName()
+ " interrupted " + e);
}
}
public static int generateRandom() {
Random random = new Random();
return random.nextInt(10);
}
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer();
for (int i = 0; i < 4; i++) {
if (i % 2 == 0)
new Thread(pc, "producer thread").start();
else {
new Thread(pc, "consumer thread").start();
}
}
}
public void run() {
while (true) {
if (getThreadName().equalsIgnoreCase("producer thread")) {
producer();
} else {
consumer();
}
}
}
}
It struck as below output:
Consumer of consumer thread in synchronized block extracted value 0 of index 0
Producer of producer thread in synchronized block i-1
Producer of producer thread in synchronized block i-1
Consumer of consumer thread is waiting i -1
Consumer of consumer thread is waiting i -1
Your code is incorrect in many places.
I expect that all threads just finish with exceptions, either because of
IllegalMonitorException (calling notify() on ProducerConsumer object
but there is no synchronized block on this ProducerConsumer object)
ArrayIndexOfBoundsException (i can become 10 in produce() method)
Have you checked error output?
Java provides a neat implementation of concurrent programs via its java.util.concurrent package. So rather than trying to reinvent the wheel, and getting it all wrong, you should use the Concurrent API to handle locking in a safer way. Here's a simulation of a Producer-Consumer:
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* We want a Producer thread to create random values, and the Consumer thread to
* consume it. One caveat is that if the Producer has already created a random
* value, which the Consumer thread hasn't consumed yet, the Producer thread
* blocks or waits. On the flip side, the Consumer thread waits for the Producer
* thread to produce some value if the Producer thread hasn't already.
* <p/>
* Write a Program to simulate such a situation.
*/
public class ProducerConsumerCommunication
{
private volatile boolean running = true;
private ArrayBlockingQueue<Integer> buffer = new ArrayBlockingQueue<>(1);
private Random random = new Random(System.currentTimeMillis());
public ProducerConsumerCommunication()
{
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new ProducerTask());
service.execute(new ConsumerTask());
service.shutdown();
}
public static void main(String[] args)
{
new ProducerConsumerCommunication();
}
private class ProducerTask implements Runnable
{
public void run()
{
while (running)
{
try
{
Thread.sleep(random.nextInt(2000));
Integer value = random.nextInt();
buffer.put(value); // Blocks if buffer is full.
System.out.println("Value Put: " + value);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
private class ConsumerTask implements Runnable
{
public void run()
{
while (running)
{
try
{
Thread.sleep(random.nextInt(2000));
Integer value = buffer.take(); // Blocks if buffer is empty.
System.out.println("Value Taken: " + value);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
Try running it and see for yourself as to how easy and intuitive it is to implement such scenarios using the Concurrent API. It also keeps your code clean and lets you focus on the problem at hand.
Reasons for deadlock in Producer Consumer problem aren't that many. If one thread has lock on an object A and is waiting for lock on object B to be released, while if other thread has lock on object B at the same time and is waiting for lock on object A to be released, deadlock situation arises.
Related
I tried to print odd number in one thread and even number in another. I tried creating two thread and printing it in run method.
public class OddEven
{
private final int MAX = 10;
private static int counter = 0;
private volatile boolean isOdd = true;
public synchronized void printEven(int counter)
{
try {
if (!isOdd) {
System.out.println(Thread.currentThread().getName() + " " + counter);
counter++;
isOdd = true;
}
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void printOdd(int counter)
{
if (isOdd) {
counter++;
System.out.println(Thread.currentThread().getName() + " " + counter);
isOdd = false;
}
notifyAll();
}
public static void main(String[] args) {
OddEven oddEven = new OddEven();
Thread th1 = new Thread() {
public void run() {
while (OddEven.counter < oddEven.MAX) {
oddEven.printEven(OddEven.counter);
}
}
};
th1.setName("even -");
th1.start();
Thread th2 = new Thread() {
public void run() {
while (OddEven.counter < oddEven.MAX) {
oddEven.printOdd(OddEven.counter);
}
}
};
th2.setName("odd -");
th2.start();
}
}
But it is printing it like below infinitely.
even - 0
odd - 1
even - 0
odd - 1
even - 0
odd - 1
To read: Is Java "pass-by-reference" or "pass-by-value"?
You pass in a primitive. counter++; makes sense only within the method and has no impact on the outer world. count refers to the method param, not to the field this.count.
There is no proper synchronisation placed upon the condition OddEven.counter < oddEven.MAX, so different things may happen.
My advice would be to remove isOdd and do a check on the spot. For instance,
public synchronized void printEven() {
if (counter % 2 != 0) {
System.out.println(Thread.currentThread().getName() + " " + ++counter);
}
}
The line oddEven.printEven(OddEven.counter) passes an integer by value to the printEven method which does not change the value of OddEven.counter when it does counter++ as also pointed in other answers here.
To get the desired output, one option is to remove the passed parameter to both printEven and printOdd methods. And there are many other ways to achieve what you are trying to do here.
And there is also a mistake in the printEven method. counter++; needs to be before the print statement.
This will give you the desired output.
In the problem I am trying to solve, each thread has to read the whole file, (maybe each thread will deliver its content to another task or any other purpose). After reading it, the thread should sleep a bit then try to read the file again, and only a given number(n) of threads should read the file. My attempt to solve this dealing with controling the amount of threads working is in the code below :
import java.util.*;
class Reader implements Runnable{
Thread t;
Controler c;
public Reader(Controler c){
t = new Thread(this);
this.c = c;
t.start();
}
public void run(){
Random ran = new Random();
int napTime;
while(true){
try{
w.intentarLeerArchivo(t);
//Specification says that each reader
//should wait a bit before trying to
//read the file again
napTime = ran.nextInt(1000);
t.sleep(napTime);
}catch(InterruptedException e){
System.out.println("InterruptedException");
}
}
}
}
class Controler{
Random ran;
LinkedList <Reader> readers;
int n;
int count;
public Controler(int n){
readers = new LinkedList <Reader>();
this.n = n;
count = 0;
ran = new Random();
}
public synchronized void getPermission(){
try{
while(count >= n){
wait();
}
notify();
}catch(InterruptedException e){
System.out.println("InterruptedException");
}
}
public synchronized void increaseCount(){
count++;
}
public synchronized void decreaseCount(){
count--;
System.out.println("There are " + count + " threads reading");
}
public void intentarLeerArchivo(Thread t){
int readTime = 1000;
try{
getPermission();
System.out.println("Thread " + t.getId() +" empezó a leer");
increaseCount();
t.sleep(readTime);
System.out.println("Thread " + t.getId() +" is reading");
System.out.println("Thread " + t.getId() + " finished reading");
decreaseCount();
} catch(InterruptedException e){
System.out.println("InterruptedException");
}
}
}
class Initializer{
int numReaders;
int maxReaders;
public Initializer(int numReaders, int maxReaders){
this.numReaders = numReaders;
this.maxReaders = maxReaders;
}
public void init(){
Controler c = new Controler(maxReaders);
for(int i = 0; i < numReaders; i++){
new Reader(c);
}
}
}
public class FileShare{
public static void main(String [] args){
Initializer c = new Initializer(100, 50);
c.init();
}
}
There are a few lines I wrote in order to debug. They print the state of each thread and the number of threads that are reading whenever one of them ends reading. But when I run the program, it turns out that suddenly there are more Threads reading the file than the ones there were supposed to be doing so. I guess it has something to do with my synchronization manipulation. What am I doing wrong?
When a thread is in the
while(...){wait()}
section of your implementation, it wait until someone notify it to go on. Right now, when you finish waiting, you notify right away.
Think about it, if once I get in I notify someone to come, he will not wait until I'm done before coming in. You want to use notify when you leave the file.
I was going through java doc description of lockInterruptibly method in ReentrantLock class. My intention was to see if the threads waiting to acquire lock are getting interrupted, may be I am doing it horribly wrong. I know there is an explicit way to call interrupt on Thread and it might be that executorService that I am using has wrapped that concept under it's API.
This behavior is seen with lock method as well
My purpose is to learn this concept in detail
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
public class LockInterruptibly extends Thread {
static ExecutorService es = Executors.newFixedThreadPool(5);
static Lock lock1 = new java.util.concurrent.locks.ReentrantLock();
public void methodA() {
if (lock1.tryLock()) {
try {
lock1.lockInterruptibly();
System.out.println("lock acquired by " + this.getName() + " of method A");
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("this thread " + this.getName() + " was interrupted");
e.printStackTrace();
}
} else {
System.out.println(this.getName() + "failed to acquire lock");
}
}
public void methodB() {
for (int i = 0; i < 5; i++) {
System.out.println("Printed by " + this.getName() + " - " + i);
}
lock1.unlock();
System.out.println(this.getName() + " is exiting at time " + new Date(System.currentTimeMillis()));
}
#Override
public void run() {
methodA();
methodB();
}
public static void main(String args[]) {
System.out.println(new Date(System.currentTimeMillis()));
for (int i = 0; i < 10; i++) {
Runnable r = new Thread(new LockInterruptibly());
es.submit(r);
}
System.out.println(new Date(System.currentTimeMillis()));
}
}
Now look at the console output below :
console logs showing the relative order, when each thread acquires lock and releases it
My questions is:
1)Why is this interleaving behavior? Why more than 1 thread are able to acquire lock (at least according to console output) , it's almost like a recursive behavior of acquiring locks. or is it just because console output is not in sync with what is happening actually?
2) Has it something to do with executor's way of treating time consuming threads and is normal behavior?
Thanks for your comments ! I was reading about the new Lock api and how you can try to lock before actually 'acquiring' it. So I wanted to code whether the threads are really non blocking or not. The updated code above assigns 5 threads and 10 tasks to executor. All the threads which fail to acquire lock, go on to print the 'for' loop. That means they are "not busy waiting" while the lock-acquiring thread is working in 'critical section'
In contrast I also implemented the synchronized way of doing it
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Synchronized extends Thread {
static ExecutorService es = Executors.newFixedThreadPool(5);
static ArrayList<Object> toBeLocked = new ArrayList<Object>();
public void methodA() {
synchronized (toBeLocked) {
try {
System.out.println("lock acquired by " + this.getName() + " of method A");
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("this thread " + this.getName() + "was interrupted");
}
}
for (int i = 0; i < 5; i++) {
System.out.println("Printed by " + this.getName() + " - " + i);
}
System.out.println(this.getName() + " is exiting at time " + new Date(System.currentTimeMillis()));
}
#Override
public void run() {
methodA();
}
public static void main(String args[]) {
System.out.println(new Date(System.currentTimeMillis()));
for (int i = 0; i < 10; i++) {
Runnable r = new Thread(new Synchronized());
es.submit(r);
}
System.out.println(new Date(System.currentTimeMillis()));
}
}
and found out that indeed all those threads were busy-waiting . Now with the new way of doing it I observed that all the threads which failed to acquire lock went ahead and never cared about returning .Are there any design patterns that answer both, optimum use of thread pools and being able to notify the next most worthy candidate.
I'm trying to get into the nitty gritty of understanding how wait and notifyAll work and have hit a roadblock.
This program downloads a long text document, starts multiple threads to count characters and then outputs the count totals.
I'm using wait and notifyAll to control the thread execution so that they are completed in alphabetical order. Here's the code. I'll follow with an explanation of the problem.
public class Test {
public static void main(String[] args) {
//code that reads in the data
LongTask a = new LongTask(buffer, 'a', "Thread_a", 0);
a.start();
LongTask b = new LongTask(buffer, 'b', "Thread_b", 1);
b.start();
//Repeat code for all other characters
a.join();
System.out.println("Alphabet count is: " + SharedResults.getResults());
LongTask class contains constructor and run()
public class LongTask extends Thread {
//Instance variables created here
//LongTask constructor
public LongTask (StringBuffer buffer, char target, String name, int turn)
{
super(name);
this.sharedData = sharedData;
inputData = buffer;
this.target = target;
this.turn = turn;
}
//Run method iterates through input data and counts matching characters,
//then calls addToResults
public synchronized void run()
{
//Thread t = Thread.currentThread();
String name = this.getName();
int runTurn = this.turn;
System.out.println(name + " running - Turn " + runTurn);
Integer count = 0;
for (int i = 0; i < inputData.length(); i++) {
if (inputData.charAt(i) == target) {
count ++;
}
}
ResultsEntry newResult = new ResultsEntry(count, target);
SharedResults.addToResults(newResult, turn);
}
}
SharedResults class adds results to Array. addToResults method performs this action and controls the synchronization.
public class SharedResults extends Thread{
//Code that creates array
//Code for SharedResults constructor
public synchronized static void addToResults(ResultsEntry newResult, int turn)
{
Integer resultsCount = newResult.getCount();
char resultsTarget = newResult.getTarget();
Thread t = Thread.currentThread();
/*
* Turn number is compared to the size of the results array to control the
* order of execution.
*/
while (turn != results.size()){
try {
System.out.println("Wait printout");
t.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(t.getName() + " is adding " + newResult);
SharedResults input = new SharedResults(resultsCount, resultsTarget);
System.out.println("Cumulative Results are " + results);
t.notifyAll();
}
Here's what I'm seeing when I watch this step through in Debug.
-Input executes and all LongTask threads start
(Thread_a should be the first thread to execute addToResults)
-Some threads (not Thread_a) hit the while evaluation of addToResults and do not proceed
-Thread_a hits the while evaluation and fully executes. (Now it should be Thread_b's turn)
-Thread_e executes the "Wait printout" (just a debugging feature that tells me when a thread is waiting) and then the program hangs.
It looks to me like I haven't set up wait correctly. The program actually worked (or appeared to be) correctly until I added in the sysout. Any ideas what's going on here?
To answer my own question,
This was covered in this thread.
The problem is that notifyAll() notify all of that object's threads that are waiting. Because I was calling wait() on each thread, the notifyAll() from another thread wasn't notifying any of the other threads.
As suggested by the linked post, I created a static synchronized object and called the wait and notify methods on that object. The resulting code looked like this:
private static final Object LOCK = new Object();
public static void addToResults(ResultsEntry newResult, int turn)
{
Integer resultsCount = newResult.getCount();
char resultsTarget = newResult.getTarget();
Thread thread = Thread.currentThread();
/*
* Turn number is compared to the size of the results array to control the
* order of execution.
*/
synchronized (LOCK){
while (turn != results.size()){
try {
System.out.println(thread.getName() + " is waiting");
LOCK.wait();
} catch (InterruptedException e) {}
}
System.out.println(thread.getName() + " is adding " + newResult);
SharedResults input = new SharedResults(resultsCount, resultsTarget);
System.out.println("Cumulative Results are " + results);
LOCK.notifyAll();
}
}
Thanks to all who commented!
i tried to add 1 to "global counter" by every Thread. So the result of "global counter" must be 10.
I printout every thread result. Most time the last result is 10. but some time the 10 is not the last number. I used synchronized or lock, but its not working.
Thank you. I hope my english is not too bad.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Hauptprogramm {
public static final int MAX_THREADS = 10;
public static int globalCounter;
public static void main(String[] args) {
// create a pool of threads, 10 max jobs will execute in parallel
ExecutorService threadPool = Executors.newFixedThreadPool(MAX_THREADS);
// submit jobs to be executing by the pool
for (int i = 0; i < MAX_THREADS; i++) {
threadPool.submit(new Runnable() {
public void run() {
// some code to run in parallel
globalCounter++;
String originalName = Thread.currentThread().getName();
System.out.println("Result: "+globalCounter+" "+originalName);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
});
}
threadPool.shutdown();
}
}
I was wandered what has been expected from this test, as I don't have 50 reputation yet, I can not add comments.
Java thread is running in JVM where there's no control in resource allocation from high level, if you are inquired to have thread that start execution after another, use release-lock mechanism, but there's no guarantee that it will do sequentially, if you inquired to do it sequentially you need to do some logic for recognition of what thread required to be executed after one another.
i think this is right now:
public void run() {
synchronized(Hauptprogramm.class)
{
globalCounter++;
String originalName = Thread.currentThread().getName();
System.out.println("Result: " + globalCounter + " " + originalName);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}});
}
threadPool.shutdown();
}
}