Reentrant Lock , busy waiting resolved by the new tryLock method - java

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.

Related

Control amount of threads reading a file in java (only using synchronized, wait, notify and sleep)

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.

Java program freezes when using wait and notifyAll

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!

beginner | threadPool | printout every result | wrong result

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();
}
}

reasons for deadlock in producer/consumer and debugging

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.

Can multilevel locks cause deadlocks in multithread programs?

I have a program with writers and readers and their access right is controlled by a monitor.
So, this was supposed to starve, but I got a deadlock. I was wondering why and then I remembered that I put another lock, which I think was unnecessary inside my read method inside readers to protect my global variable from inconsistencies. I thought it wouldn't cause any deadlock, because I could run the threads 10000 time without any deadlock occurring, but when I had to do my lab demo, it deadlocked at the 10010th thread I think. I don't understand why it would do that though. Also, I didn't expect it to starve, but apparently it was supposed to.
My question is: are those multilevel locks responsible for the deadlock? If not, what's causing this?!
import java.io.*;
import java.io.IOException;
import java.util.*;
public class Writer extends Thread{
private int number;
public Writer(int number)
{
this.number = number;
}
public int getNumber()
{
return number;
}
public static void Write(String filename){
try {
String content = RandomString();
File f = new File(filename);
if (!f.exists())
{
f.createNewFile();
}
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("Task1out.txt", true)));
out.println(content);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static String RandomString(){
String chars = new String("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
int n = chars.length();
String randomString = new String();
Random r = new Random();
for (int i=0; i<100; i++)
{
randomString = randomString + chars.charAt(r.nextInt(n));
}
System.out.println("RandomString() generated: " + randomString);
return randomString;
}
public void run(){
try{
//FileControl fc = new FileControl();
int number = this.getNumber();
for(int i = 0; i <1000; i++) //CHANGE IT TO 1000
{
main.fc.WriterEntry(number);
//write file random characters (must append)
Write("Task1out.txt");
main.fc.WriterExit(number);
}
} catch(InterruptedException e)
{
System.out.println("Interrupted Exception caught");
}
}
}
This is the writer class.
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Reader extends Thread{
private int number;
public Reader(int number)
{
this.number = number;
}
public int getNumber()
{
return number;
}
public static synchronized void Read(String filename)throws InterruptedException{
BufferedReader br = null;
main.lock.lock(); //lock
try{
try {
String line;
char[] chars = new char[100];
int readIndex2 = 0;
int addToIndex = 0;
br = new BufferedReader(new FileReader(filename));
int initialReadIndex = main.getIndex();
System.out.println("initial read index: " + initialReadIndex);
while ((line = br.readLine()) != null && readIndex2 < initialReadIndex+100 && addToIndex < 100) {
for(int i = 0; i< 100; i++)
{
if (initialReadIndex == readIndex2 || initialReadIndex < readIndex2)
{
if(line.length() > addToIndex)
{
chars[i] = line.charAt(i);
addToIndex++;
}
}
else
{
readIndex2++;
}
}
System.out.println(chars);
}
if(line == null)
{
System.out.println("nothing to read");
}
main.incrementIndex(addToIndex);
System.out.println("current read index: " + (initialReadIndex + addToIndex));
} catch (IOException e) {
e.printStackTrace();
System.out.println("buffered reader exception");
} finally {
try {
if (br != null)
{
br.close();
}
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("exception during closing");
}
}
}finally{
main.lock.unlock(); //lock
}
}
public void run(){
try{
//FileControl fc = new FileControl();
int number = this.getNumber();
for(int i = 0; i <1000; i++) //CHANGE IT TO 1000
{
main.fc.ReaderEntry(number);
//read file
Read("Task1out.txt");
main.fc.ReaderExit(number);
}
} catch(InterruptedException e)
{
System.out.println("Interrupted Exception caught");
}
}
}
This is the reader class.
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class main{
public static FileControl fc = new FileControl();
final static Lock lock = new ReentrantLock();
public static int readIndex;
public static void incrementIndex(int increment) {
readIndex = readIndex + increment;
}
public static int getIndex()
{
return readIndex;
}
public static void main(String[] args) throws InterruptedException {
Writer [] writer = new Writer[10];
Reader [] reader = new Reader[10];
for(int i = 0; i < 10; i++)
{
reader[i] = new Reader(i);
writer[i] = new Writer(i);
//creating readers and writers
}
for(int i = 0; i < 10; i++)
{
//anonymous threads
//(new Thread(new Writer())).start();
//(new Thread(new Reader())).start();
reader[i].start();
writer[i].start();
}
for(int i = 0; i < 10; i++)
{
try{
reader[i].join();
writer[i].join();
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
This is the main class.
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class FileControl {
final Lock lock = new ReentrantLock();
final Condition writers = lock.newCondition();
final Condition readers = lock.newCondition();
int activereaders = 0;
int waitingwriters = 0;
boolean writing = false;
public void WriterEntry(int number)throws InterruptedException{
lock.lock();
try{
if(writing == true || activereaders > 0){
waitingwriters++;
System.out.println("Writer thread " + number + " : waiting to write");
writers.await();
waitingwriters--;
}
System.out.println("Writer thread " + number + " : ready to write");
writing = true;
}
finally{
lock.unlock();
}
}
public void WriterExit(int number)throws InterruptedException{
lock.lock();
try{
System.out.println("Writer thread " + number + " : finished to write");
System.out.println("writers " + waitingwriters + "readers " + activereaders); //test
if(waitingwriters > 0)
writers.signal();
else{
writing = false;
readers.signal();
}
}
finally{
lock.unlock();
}
}
public void ReaderEntry(int number)throws InterruptedException{
lock.lock();
try{
if(writing == true || waitingwriters > 0){ //remove activereaders > 0
System.out.println("Reader thread " + number + " : waiting to read");
readers.await();
activereaders++;
}
System.out.println("Reader thread " + number + " : ready to read");
}
finally{
lock.unlock();
}
}
public void ReaderExit(int number)throws InterruptedException{
lock.lock();
try{
activereaders--;
System.out.println("Reader thread " + number + " : finished to read");
System.out.println("writers " + waitingwriters + "readers " + activereaders); //test
if(activereaders == 0)
{
if(waitingwriters > 0)
{
writers.signal();
}
else
{
readers.signal();
}
}
}
finally{
lock.unlock();
}
}
}
This is the monitor.
pseudocode for the monitor
Whenever you have multiple locks A, B and C you can have deadlock if you don't guarantee that your code attempts to acquire said locks in the same order.
final Lock A = new ReentrantLock();
final Lock B = new ReentrantLock();
final Lock C = new ReentrantLock();
A,B,C or C,B,A, or A,C,B - it does not matter so long as the order is consistent.
A problem arises when you have one code path try for: A,B,C
And another trying for C,B,A.
As you can probably guess since A and C are both being held, one of the two will get B and then both will deadlock. (Aka you have a cycle in the resource locking graph)
Formally speaking deadlock can arise only if all of the following conditions hold:
No Preemption: The system will not free resources after allocation;
they can only be released by the holding process.
Circular Wait: Discussed above.
Mutual Exclusion: Only one process can use a resource at any given time.
Resource Holding: A process is currently holding at least one resource and requesting/waiting for additional resources which are held by another process.
The best solution is to make sure the order is consistent or lock at a higher (single) level. Another option is to use a locking library that will timeout while attempting to lock (or use conditions and write your own wrapper that does this). But that approach is not for the faint of heart. Some implementation of this will wait a random amount of time and try again, but this can be highly inefficient as the number of locks increases.
Resources:
Here is a practical article on analyzing deadlock in Java that you
might be interested in:
http://www.journaldev.com/1058/java-deadlock-example-and-how-to-analyze-deadlock-situation
You can also use open source tools like JCarder to find deadlock:
http://www.jcarder.org/ which for programs with large dumps can be
easier then trying to grok dump files.
P.S. I didn't actually read much of your code since its poorly formatted and and is not a minimal example (ie. too verbose for our purposes here). But this advice should answer you question from a theoretical standpoint.
It's certainly possible. It's also possible for you to check at runtime!
The first step is to get the thread dump. Here are three methods:
If you open up the process in VisualVM, and go to the "threads" tab, it'll tell you if it detects this sort of a deadlock. You can then do a thread dump (there's a button right there), which will tell you what each thread is doing, as well as any locks it owns and any which locks (if any) it's trying to acquire.
On Linux or Mac, you can get the stack by issuing kill -3 <pid>, where <pid> is your java process' id. It'll dump that same thread dump to stderr. The bottom of that thread dump will also contain a summary of deadlocks it detects. I don't know how to do this on Windows.
You can also invoke jstack <pid>, which will print the thread dump to stdout (the jstack's stdout, not the original java process').
I wrote up a sample program that deadlocks and ran it (see my gist). The relevant section of the thread dump is:
Found one Java-level deadlock:
=============================
"Thread-2":
waiting for ownable synchronizer 7f42b0f38, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
which is held by "Thread-1"
"Thread-1":
waiting for ownable synchronizer 7f42ba170, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
which is held by "Thread-2"
And the relevant thread states are:
"Thread-2" prio=5 tid=7fc01c911000 nid=0x113d18000 waiting on condition [113d17000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <7f30c3528> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
at Locky$Boomer.run(Locky.java:22)
at java.lang.Thread.run(Thread.java:680)
Locked ownable synchronizers:
- <7f30c3558> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"Thread-1" prio=5 tid=7fc01d06c800 nid=0x113c15000 waiting on condition [113c14000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <7f30c3558> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
at Locky$Boomer.run(Locky.java:22)
at java.lang.Thread.run(Thread.java:680)
Locked ownable synchronizers:
- <7f30c3528> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
This will not work on all deadlocks. For instance, deadlocks due to waiting on external resources won't get caught. But it'll catch Lock-based deadlocks, as well as synchronized-based ones.

Categories