Java - How to detect deadlocks and recovery from this? - java

Right now I write a Java program that has as purpose detect deadlocks and recovery from this situation. The program input is two numbers, N = Number of types of resources and M = Number of process.
I wanted to do something like this:
private static void test2() {
final ReentrantLock lock1 = new ReentrantLock();
final ReentrantLock lock2 = new ReentrantLock();
Thread thread1 = new Thread(new Runnable() {
#Override public void run() {
try {
lock1.lock();
System.out.println("Thread1 acquired lock1");
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException ignore) {}
lock2.lock();
System.out.println("Thread1 acquired lock2");
}
finally {
lock2.unlock();
lock1.unlock();
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
#Override public void run() {
try {
lock2.lock();
System.out.println("Thread2 acquired lock2");
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException ignore) {}
lock1.lock();
System.out.println("Thread2 acquired lock1");
}
finally {
lock1.unlock();
lock2.unlock();
}
}
});
thread2.start();
// Wait a little for threads to deadlock.
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException ignore) {}
detectDeadlock();
}
But instead of 2, N locks and I have several problems for doing this. Here my code with my attempt:
class Main {
private static int MAX_AVAILABLE = 10;
private static int IDLE = 1000;
public static void main(String[] args) throws java.lang.Exception{
int n, m; //number of resources and process, respectively
ReentrantLock[] resources; // Locks for resources
int[] available; // Number of instances per resource
Process[] processes; // Processes array
DeadlockDetector supervisor; // Deadlock detaction class
n = Integer.valueOf(args[0]);
m = Integer.valueOf(args[1]);
resources = new ReentrantLock[n];
available = new int[n];
processes = new Process[m];
supervisor = new DeadlockDetector();
// Create resources array
for(int i=0; i<n; ++i){
available[i] = (int)(Math.floor(Math.random()*MAX_AVAILABLE + 1));
resources[i] = new ReentrantLock();
System.out.println("R"+String.valueOf(i+1)+"-> instances: "+String.valueOf(available[i]));
}
// Creating processes
for(int i=0; i<m; ++i){
processes[i] = new Process(i, resources, available, n);
System.out.println("P"+String.valueOf(i+1)+"-> requested "+Arrays.toString(processes[i].requested));
processes[i].start();
}
//Run deadlock detection
try {
TimeUnit.MILLISECONDS.sleep(IDLE);
}catch (InterruptedException ignore){}
supervisor.start();
}
}
class Process extends Thread{
public int id;
public int total; // Total of resources instances needed for finished the process
public ReentrantLock[] resources;
public int[] requested; // Number of instances needed per resource type
public boolean[] needed; // Boolean indicating whether the process needs at least one instance of the resource i
public int n;
private static int MIN_TIME = 1000;
private static int MAX_TIME = 3000;
public Process(int index, ReentrantLock[] res, int[] available, int n_resources){
id = index;
n = n_resources;
resources = res;
total = 0;
requested = new int[n];
needed = new boolean[n];
for(int i=0; i<n; ++i){
requested[i] = (int)(Math.floor(Math.random()*available[i]));
needed[i] = requested[i] > 0;
total += requested[i];
}
}
#Override
public void run(){
int resourceT = 0;
int timeToSleep;
System.out.println("P"+String.valueOf(id+1)+" begin running");
try{
while(total > 0){
resourceT = (int)(Math.floor(Math.random()*n));
if(requested[resourceT] < 1){
System.out.println("P"+String.valueOf(id+1)+"-> I do not need more R"+String.valueOf(resourceT+1));
continue;
}
System.out.println("P"+String.valueOf(id+1)+"-> I'll take R"+String.valueOf(resourceT+1));
resources[resourceT].lock();
timeToSleep = (int)(Math.floor(Math.random()*(MAX_TIME - MIN_TIME)) + MIN_TIME);
try{
TimeUnit.MILLISECONDS.sleep(timeToSleep);
}catch (InterruptedException ignore){}
--total;
--requested[resourceT];
}
}finally{
for(int i=0; i<n; ++i){
if(needed[i] && resources[i].isHeldByCurrentThread())
resources[i].unlock();
}
}
System.out.println("P"+String.valueOf(id+1)+"-> Im finished");
}
}
class DeadlockDetector extends Thread{
public ThreadMXBean threadBean;
public long[] threadIds;
public DeadlockDetector(){
}
#Override
public void run(){
Boolean good;
this.threadBean = ManagementFactory.getThreadMXBean();
threadIds = threadBean.findDeadlockedThreads();
int deadlockedThreads = threadIds != null? threadIds.length : 0;
if(deadlockedThreads>1){
good = false;
System.out.println("Number of deadlocked threads: " + deadlockedThreads);
//recoverDeadlock();
//break;
}
}
public void recoverDeadlock(){
}
}
Please, could anyone help me fix this detail? Thanks!

Related

Java multiple thread join issue

So i need to process a couple data files using threads (already splitted), and i'm having issues on how to stop the main thread till all the subthreads finish.
i looked around and tried to use join() but this causes an issue:
If i join the main thread with the last thread then since the other threads run at the same time, the last thread is not always the last one to finish
If i join the main thread with all the other threads then they don't run at the same time, the second needs the first to finish first.
also tried wait() and notify() but had even more issues. here's a part of my code
public class Matrix extends MapReduce {
ArrayList<String> VecteurLines = new ArrayList<String>();
protected int[] nbrLnCol = {0,0};
protected static double[] res;
public Matrix(String n) {
super(n);
}
public Matrix(String n,String m){
super(n,m);
}
public void Reduce() throws IOException, InterruptedException, MatrixException {
for (int i = 1; i <= Chunks; i++) {
Thread t=new Thread(new RunThread(VecteurLines,i,this));
t.start();
}
}
And here's the class that handles the threads
public class RunThread extends Matrix implements Runnable {
Matrix ma;
ArrayList<String> vec;
int threadNbr;
public RunThread(ArrayList<String> vec, int threadNbr,Matrix ma) {
super("","");
this.vec=vec;this.threadNbr=threadNbr;this.ma=ma; }
#Override
public void run() {
FileInputStream fin = null;
try {
fin = new FileInputStream(ma.getNom()+threadNbr+".txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Scanner sc = new Scanner(fin);
while (sc.hasNext()) {
String nextString = sc.next();
ma.nbrLnCol[0]++;
String [] arr = nextString.split(",");
ma.nbrLnCol[1]=arr.length;
double c=0;
for(int j=0;j<arr.length;j++)
{
c+=(Double.parseDouble(arr[j])*Double.parseDouble(vec.get(j)));
}
res[threadNbr-1]=c;
}
sc.close();
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
File file = new File(ma.getNom()+threadNbr+".txt");
file.delete();
}
Try like this:
private List<Thread> threadList = new ArrayList<>();
public void Reduce() {
threadList.clear();
for (int i = 1; i <= Chunks; i++) {
Thread t =new Thread(new RunThread(VecteurLines,i,this));
threadList.add(t);
}
// start all worker threads
for(int i=0; i<threadList.size(); i++){
threadList.get(i).start();
}
// wait until all worker threads is finished
while (true) {
int threadIsNotLive = 0;
for (int i = 0; i < threadList.size(); i++) {
Thread t = threadList.get(i);
if (!t.isAlive() || t == null) {
++threadIsNotLive;
}
}
if(threadIsNotLive>0 && (threadList.size() == threadIsNotLive)){
break;
// all worker threads is finished
}
else {
Thread.sleep(50);
// wait until all worker threads is finished
}
}
}
OR
public void Reduce() {
List<Thread> threadList = new ArrayList<>();
for (int i = 1; i <= Chunks; i++) {
Thread t =new Thread(new RunThread(VecteurLines,i,this));
threadList.add(t);
}
// start all worker threads
for(int i=0; i<threadList.size(); i++){
threadList.get(i).start();
threadList.get(i).join();
}
}
I believe you need two points in your code:
Your main thread has to end last after all the thread's executed because you said
"how to stop the main thread till all the subthreads finish"
.
Second ,the thread should finish one after another that is the 2nd thread should finish after 1st thread as you said
"the second needs the first to finish first."
Here is my code to do it with join .
public class Matrix extends MapReduce {
ArrayList<String> VecteurLines = new ArrayList<String>();
protected int[] nbrLnCol = {0,0};
protected static double[] res;
public Matrix(String n) {
super(n);
}
public Matrix(String n,String m){
super(n,m);
}
public void Reduce() throws IOException, InterruptedException, MatrixException {
Thread t = null;
for (int i = 1; i <= Chunks; i++) {
Thread t=new Thread(new RunThread(t,VecteurLines,i,this));
t.start();
}
t.join(); // finally main thread joining with the last thread.
}
and
public class RunThread extends Matrix implements Runnable {
Matrix ma;
ArrayList<String> vec;
int threadNbr;
Thread t;
public RunThread(t,ArrayList<String> vec, int threadNbr,Matrix ma) {
this.t = t;
super("","");
this.vec=vec;this.threadNbr=threadNbr;this.ma=ma; }
#Override
public void run() {
FileInputStream fin = null;
try {
fin = new FileInputStream(ma.getNom()+threadNbr+".txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Scanner sc = new Scanner(fin);
while (sc.hasNext()) {
String nextString = sc.next();
ma.nbrLnCol[0]++;
String [] arr = nextString.split(",");
ma.nbrLnCol[1]=arr.length;
double c=0;
for(int j=0;j<arr.length;j++)
{
c+=(Double.parseDouble(arr[j])*Double.parseDouble(vec.get(j)));
}
res[threadNbr-1]=c;
}
sc.close();
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
File file = new File(ma.getNom()+threadNbr+".txt");
file.delete();
if(t!=null){
t.join(); //join with the previous thread eg. thread2 joining with thread1
}
}

why all producer threads also exit when comsumer threads all exit

I am running the below code, and I have one question:
why do all producer threads also exit when the consumer threads all exit.
Here is the code:
public class NumbersConsumer implements Runnable {
private final BlockingQueue<Integer> queue;
private final int poisonPill;
NumbersConsumer(BlockingQueue<Integer> queue, int poisonPill) {
this.queue = queue;
this.poisonPill = poisonPill;
}
public void run() {
try {
while (true) {
Integer number = queue.take();
if (number.equals(poisonPill)) {
return;
}
String result = number.toString();
System.out.println(Thread.currentThread().getName() + " result: " + result);
}
} catch (InterruptedException e) {
System.out.println(e.getStackTrace());
Thread.currentThread().interrupt();
}
}
}
Producer:
public class NumbersProducer implements Runnable {
private final BlockingQueue<Integer> numbersQueue;
private final int poisonPill;
private final int poisonPillPerProducer;
NumbersProducer(BlockingQueue<Integer> numbersQueue, int poisonPill, int poisonPillPerProducer) {
this.numbersQueue = numbersQueue;
this.poisonPill = poisonPill;
this.poisonPillPerProducer = poisonPillPerProducer;
}
public void run() {
try {
generateNumbers();
} catch (InterruptedException e) {
System.out.println(e.getStackTrace());
Thread.currentThread()
.interrupt();
}
}
private void generateNumbers() throws InterruptedException {
for (int i = 0; i < 100; i++) {
numbersQueue.put(ThreadLocalRandom.current()
.nextInt(100));
}
for (int j = 0; j < poisonPillPerProducer; j++) {
numbersQueue.put(poisonPill);
}
}
}
Tester:
public class BlockingQueueUsage {
public static void main(String[] args) {
int BOUND = 10;
int N_PRODUCERS = 4;
int N_CONSUMERS = Runtime.getRuntime().availableProcessors();
int poisonPill = Integer.MAX_VALUE;
int poisonPillPerProducer =N_CONSUMERS / N_PRODUCERS ;
System.out.printf("poisonPillPerProducer:%s,N_CONSUMERS:%s %n",poisonPillPerProducer,N_CONSUMERS);
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(BOUND);
for (int i = 0; i < N_PRODUCERS; i++) {
new Thread(new NumbersProducer(queue, poisonPill, poisonPillPerProducer),"Producer"+i).start();
}
for (int j = 0; j < N_CONSUMERS; j++) {
new Thread(new NumbersConsumer(queue, poisonPill),"comsumer"+j).start();
}
}
}
Simple: your producers are missing a loop.
The produces do nothing but produce some numbers, and that poison pill that will end the consumers.
The consumers on the other hand, would be consuming forever ... until that pill comes in.
In other words: your producers "end", because they aren't designed to stay alive.

Why does not thread join?

I want to measure thread execution
I wrote following code:
public class Task5 {
public static int [] readerThreadCount = {10};
public static int [] writerThreadCount = {1};
public static void main(String[] args) throws InterruptedException {
for (int readCount : readerThreadCount) {
for (int writeCount : writerThreadCount) {
test(readCount, writeCount, new ArrayHolderBySynchronized());
}
}
}
private static void test(int readCount, int writeCount, ArrayHolder arrayHolder) throws InterruptedException {
final List<Thread> threads = new ArrayList<>();
CyclicBarrier cyclicBarrier = new CyclicBarrier(1, new Summarizer(threads, readCount, writeCount));
for (int i = 0; i < readCount; i++) {
threads.add(new Thread(new ArrayReader(arrayHolder, cyclicBarrier)));
}
for (int i = 0; i < writeCount; i++) {
threads.add(new Thread(new ArrayWriter(arrayHolder, cyclicBarrier)));
}
for(Thread thread:threads){
thread.start();
}
}
}
class Summarizer implements Runnable{
List<Thread> threads;
int readCount;
int writeCount;
Summarizer(List<Thread> threads, int readCount, int writeCount) {
this.threads = threads;
this.readCount = readCount;
this.writeCount = writeCount;
}
#Override
public void run() {
long start = System.currentTimeMillis();
System.out.println("All threads started");
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
System.out.println(readCount + "/" + writeCount + (System.currentTimeMillis() - start));
}
}
class ArrayHolderBySynchronized extends ArrayHolder {
#Override
public synchronized int get(int index) {
System.out.println("read");
return arr[index];
}
#Override
public synchronized void write(int index, int value) {
System.out.println("write");
arr[index] = value;
}
}
class ArrayReader implements Runnable {
ArrayHolder arrayHolder;
CyclicBarrier cyclicBarrier;
ArrayReader(ArrayHolder arrayHolder, CyclicBarrier cyclicBarrier) {
this.arrayHolder = arrayHolder;
this.cyclicBarrier = cyclicBarrier;
}
#Override
public void run() {
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (BrokenBarrierException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
arrayHolder.get(new Random().nextInt(ArrayHolder.ARRAY_SIZE));
}
}
class ArrayWriter implements Runnable {
ArrayHolder arrayHolder;
CyclicBarrier cyclicBarrier;
ArrayWriter(ArrayHolder arrayHolder, CyclicBarrier cyclicBarrier) {
this.arrayHolder = arrayHolder;
this.cyclicBarrier = cyclicBarrier;
}
#Override
public void run() {
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (BrokenBarrierException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
arrayHolder.write(new Random().nextInt(ArrayHolder.ARRAY_SIZE), -1);
}
}
abstract class ArrayHolder {
public static int ARRAY_SIZE = 1_000_000;
protected int[] arr = generateArray();
private int[] generateArray() {
int[] arr = new int[ARRAY_SIZE];
for (int i = 0; i < ARRAY_SIZE; i++) {
arr[i] = i + 1;
}
return arr;
}
public abstract int get(int index);
public abstract void write(int index, int value);
}
but in output I see
All threads started
But appication hangs on thread.join.
What do I wrong?
You have a deadlock in your code:
You are submitting the Summarizer instance as barrierAction to the CyclicBarrier. So when barrier trips it has to execute the Summarizer before any thread awaiting on the barrier is allowed to proceed. But the Summarizer performs thread.join() on all threads that awaiting on that CyclicBarrier.
So the CyclicBarrier is waiting for the Summarizer. The Summarizer is waiting for the threads. And threads are waiting for the CyclicBarrier.

Multithreading: How to get a thread to execute more frequently than the others?

I've recently been learning about semaphores to specify the ordering of threads, but I'm curious about how to control the frequency as well. Below is a program that prints *, a digit, and then a letter to the screen. Always in that order (e.g. *1A). How can I make it so certain threads print more than once before the others? (e.g. *32A)
import java.lang.Thread;
import java.util.concurrent.*;
public class ThreadSync {
private static boolean runFlag = true;
private static Semaphore canPrintSymbol = new Semaphore(1);
private static Semaphore canPrintDigit = new Semaphore(0);
private static Semaphore canPrintLetter = new Semaphore(0);
public static void main( String[] args ) {
Runnable[] tasks = new Runnable[17];
Thread[] threads = new Thread[17];
// Create 10-digit threads
for (int d = 0; d < 10; d++) {
tasks[d] = new PrintDigit((char)('0' + d));
threads[d] = new Thread(tasks[d]);
threads[d].start();
}
// Create 6-letter threads
for (int d = 0; d < 6; d++) {
tasks[d + 10] = new PrintLetter((char)('A' + d));
threads[d + 10] = new Thread(tasks[d + 10]);
threads[d + 10].start();
}
// Create a thread to print asterisk
tasks[16] = new PrintSymbol('*');
threads[16] = new Thread(tasks[16]);
threads[16].start();
// Let the threads run for a period of time
try { Thread.sleep(500); }
catch (InterruptedException ex) { ex.printStackTrace(); }
runFlag = false;
// Interrupt the threads
for (int i = 0; i < 17; i++) threads[i].interrupt();
}
public static class PrintSymbol implements Runnable {
private char c;
public PrintSymbol(char c) {
this.c = c;
}
public void run() {
while (runFlag) {
try {
canPrintSymbol.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf("%c\n", c);
canPrintDigit.release();
}
}
}
public static class PrintDigit implements Runnable {
private char c;
public PrintDigit(char c) { this.c=c; }
public void run() {
while (runFlag) {
try {
canPrintDigit.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf("%c\n", c);
canPrintLetter.release();
}
}
}
public static class PrintLetter implements Runnable {
private char c;
public PrintLetter(char c) {
this.c = c;
}
public void run() {
while (runFlag) {
try {
canPrintLetter.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf("%c\n", c);
canPrintSymbol.release();
}
}
}
}
Short answer is you can't. At least not to my knowledge. There are hints you can give to the OS like yielding your thread. This means it yields it processing to the next thread. Other then that all you can really do is influence the priority. But all these are just hints to the OS. The OS ultimately determines the order in which the threads are executed. This is one of the main things to keep in mind when working with multiple threads. It is generally not a good idea to have a dependency between separate threads which makes the order of execution important.

Program Threads hanging when using a semaphore

I have an issue setting up a critical section with a semaphore between 2 threads. I am using a semaphore to acquire(send) in my Customer thread and release in my teller thread. However when I run my program it is always hanging and I don't know why. I have tried several things and i am not sure what the issue was.
I am trying to use the deposit semaphore to set up a critical section with the customer thread and teller thread.
import java.util.concurrent.Semaphore;
public class Threads {
// private int customerNumber = 0;
private static Semaphore deposit = new Semaphore (0, true);
public static void main(String[] args)
{
final int customerThreads = 5;
final int tellerThreads = 2;
final int loanThreads = 1;
Customer thr[] = new Customer[customerThreads]; // make 5 customer threads
Thread cThread[] = new Thread[customerThreads]; // made 5 threads
for (int i= 0; i < customerThreads; i++)
{
thr[i]= new Customer(i);
cThread[i] = new Thread(thr [i]);
cThread[i].start();
}
for ( int i = 0; i < customerThreads; i++ )
{
try {
cThread[i].join ();
System.out.println("Customer"+i + "joined from main");
}
catch (InterruptedException e)
{
}
}
Teller thr1[] = new Teller[tellerThreads];
Thread tThread[] = new Thread[tellerThreads];
for (int b = 0; b< tellerThreads; b++)
{
thr1[b] = new Teller(b);
tThread[b]= new Thread(thr1 [b]);
tThread[b].start();
}
LoanOfficer thr2[] = new LoanOfficer[loanThreads];
Thread lThread[] = new Thread[loanThreads];
for(int c = 0; c< loanThreads; c++)
{
thr2[c] = new LoanOfficer(c);
lThread[c] = new Thread(thr2 [c]);
lThread[c].start();
}
// TODO code application logic here
}
static class Customer implements Runnable
{
private int customerNumber = 0;
private int balance = 0;
Customer(int cn)
{
this.customerNumber = cn;
balance = 1000;
System.out.println("Customer"+ customerNumber + "created");
}
public void run()
{
try
{
Thread.sleep(200);
deposit.acquire();
}
catch(InterruptedException e)
{
Thread.currentThread().interrupt();
e.printStackTrace();
}
//System.out.println("Customer"+ customerNumber + "created");
// try
}
public void post()
{
}
}
static class Teller implements Runnable
{
private int tellerNumber = 0;
Teller(int tn)
{
this.tellerNumber = tn;
System.out.println("Teller"+ tellerNumber +"created");
}
public void run()
{
deposit.release();
// try
// {
//
// // deposit.release();
//
// Thread.sleep(100);
// // deposit.acquire();
// }
// catch(InterruptedException e)
// {
// deposit.release();
// }
//System.out.println("Teller"+ tellerNumber +"created");
}
public void post()
{
}
}
static class LoanOfficer implements Runnable
{
private int loanNumber = 0;
LoanOfficer(int tn)
{
this.loanNumber = tn;
System.out.println("LoanOfficer"+loanNumber+"created");
}
public void run()
{
//System.out.println("LoanOfficer"+loanNumber+"created");
}
public void post()
{
}
}
}
You instantiate semaphore with no permits as below:
private static Semaphore deposit = new Semaphore (0, true);
Hence when you try to call acquire, you wont get the permit to execute beyond and hence blocks. So try atleast having 1 permit so at a time only 1 thread can execute post you acquire the permit from semaphore. You could increase that later as well.
private static Semaphore deposit = new Semaphore (1, true);
Refer the doc here

Categories

Resources