Question

In: Computer Science

Why is this java code reaching a deadlock and how to I fix it without serializing...

Why is this java code reaching a deadlock and how to I fix it without serializing the code (i.e. I don't want to do not have the Girl authenticate the Boy then have the Boy authenticate the Girl)?


import java.applet.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

// Attempt at a simple handshake.  Girl pings Boy, gets confirmation.
// Then Boy pings girl, get confirmation.
class Monitor {
   String name;
        
   public Monitor (String name) { this.name = name; }
                   
   public String getName() {  return this.name; }
                                
   // Girl thread invokes ping, asks Boy to confirm.  But Boy invokes ping,
   // and asks Girl to confirm.  Neither Boy nor Girl can give time to their
   // confirm call because they are stuck in ping.  Hence the handshake 
   // cannot be completed.
   public synchronized void ping (Monitor p) {
      System.out.println(this.name + " (ping): pinging " + p.getName());
      p.confirm(this);
      System.out.println(this.name + " (ping): got confirmation");
   }
                                
   public synchronized void confirm (Monitor p) {
      System.out.println(this.name+" (confirm): confirm to "+p.getName());
   }
}

class Runner extends Thread {
   Monitor m1, m2;
                
   public Runner (Monitor m1, Monitor m2) { 
      this.m1 = m1; 
      this.m2 = m2; 
   }
                                                        
   public void run () {  m1.ping(m2);  }
}
                                                                        
public class DeadLock {
   public static void main (String args[]) {
      int i=1;
      System.out.println("Starting..."+(i++));
      Monitor a = new Monitor("Girl");
      Monitor b = new Monitor("Boy");
      (new Runner(a, b)).start();
      (new Runner(b, a)).start();
   }
}

Solutions

Expert Solution

Some detail before I answer your questions:

This piece of code will not alway get stuck into the deadlock. It will only happen when both Threads tries to execute ping() method at the very same instance(sounds bizarre).

Two threads have been started immediately one after another and so it is easy to assume that they will always execute ping() method simultaneously(Boy and girl Monitor both), but that wont always be the case, one thread will seldom complete execution of method ping() before the other starts as it has very small footprint. And so in that case the code will run as expected.

So why in some cases it gets stuck into deadlock?
The reason is the use of synchronized keyword in method syntax. A synchronized method gets lock on the current object('this') before starting the execution of the method. What does that mean exactly?

public synchronized void ping(Monitor p) {

...
}

is essentially,

public void ping(Monitor p) {

        synchronized (this) {
        ......

        }

}

Which means that when m1.ping(m2) is called from Thread1 the ping() method will get hold of the lock on 'this' object(which would be m1 in this case). So, consequently no other synchronized method of 'this(m1)'s can be called until ping() releases the lock on 'this'(on m1). Now, ping() is also calling a synchronized method from within itself, albeit, some other objects(m2)'s confirm() method. Same rule would apply there also. ping() method of 'this' (m1) would want to execute m2's confirm(), BUT what if some other thread(Thread2) is doing the same with m2, i.e. calling the ping() method of m2, so holding the lock on m2. Which means m1('this') will have to wait until m2's ping() releases lock on it. BUT m2's ping() wont be able to do it as m1's confirm() cant be executed from there within as m1's ping() already has a lock on m1, ergo a deadlock.

To prevent this,

Remove dependancy of 'this' as a single lock to call both the methods of single object. What does that mean? Create two different objects that holds lock on both methods respectively. This will make sure that no two thread can execute ping() simultaneously(while same applies for confirm()), but they will not hold each other's execution(ping() and confirm() of same object can be called independently from different thread). here's the implementation.

public class Monitor {
    String name;
    final Object pingLock = new Object();
    final Object confirmationLock = new Object();

    public Monitor(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void ping(Monitor p) {
        synchronized (pingLock) {
            System.out.println(this.name + " (ping): pinging " + p.getName());
            p.confirm(this);
            System.out.println(this.name + " (ping): got confirmation");
        }

    }

    public void confirm(Monitor p) {
        synchronized (confirmationLock) {
            System.out.println(this.name + " (confirm): confirm to " + p.getName());
        }
    }
}   


Related Solutions

JAVA: How do I fix the last "if" statement in my code so that outputs the...
JAVA: How do I fix the last "if" statement in my code so that outputs the SECOND HIGHEST/MAXIMUM GPA out of the given classes? public class app { private static Object minStudent; private static Object maxStudent; public static void main(String args[ ]) { student st1 = new student("Rebecca", "Collins", 22, 3.3); student st2 = new student("Alex", "White", 19, 2.8); student st3 = new student("Jordan", "Anderson", 22, 3.1); student[] studentArray; studentArray = new student[3]; studentArray[0] = st1; studentArray[1] = st2; studentArray[2]...
Hello I have this error in the code, I do not know how to fix it....
Hello I have this error in the code, I do not know how to fix it. It is written in C++ using a Eclipse IDE Error: libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string bus.h =========== #pragma once #include using namespace std; class Bus { private:    string BusId; // bus ID    string Manufacturer; // manufacturer of the bus    int BusCapacity; // bus capacity    int Mileage; // mileage of bus    char Status; // current status...
I already have the code of this program, I just want to know how to fix...
I already have the code of this program, I just want to know how to fix the code to Implement the 5th function (System.nanotime() and System.currentTimeMillis() methods) What Code does: Introduction Searching is a fundamental operation of computer applications and can be performed using either the inefficient linear search algorithm with a time complexity of O (n) or by using the more efficient binary search algorithm with a time complexity of O (log n). Task Requirements In this lab, you...
I Have posted my Java code below. Fix the toString, add, and remove implementations so that...
I Have posted my Java code below. Fix the toString, add, and remove implementations so that the following test cases work. Note: I have removed all the unnecessary inherited List implementations. I have them to: throw new UnsupportedException(); For compilation, you could also add //TODO. Test (Main) List list = new SparseList<>(); list.add("0"); list.add("1"); list.add(4, "4"); will result in the following list of size 5: [0, 1, null, null, 4]. list.add(3, "Three"); will result in the following list of size...
I'm getting an error message with this code and I don't know how to fix it...
I'm getting an error message with this code and I don't know how to fix it The ones highlighted give me error message both having to deal Scanner input string being converted to an int. I tried changing the input variable to inputText because the user will input a number and not a character or any words. So what can I do to deal with this import java.util.Scanner; public class Project4 { /** * @param args the command line arguments...
How can I fix this code to accomplish the goal of reading and writing on binary...
How can I fix this code to accomplish the goal of reading and writing on binary or text files? 3 import java.io.*; 4 import java.io.FileOutputStream; 5 import java.io.FileInputStream; 6 import java.util.Scanner; 7 8 public class ReadAndWrite implements Serializable 9 { 10 public static void main(String[] args) 11 { 12 boolean file = true; 13 Scanner inputStream; 14 PrintWriter outputStream; 15 FileInputStream inputBinary; 16 FileOutputStream readBinary; 17 FileInputStreamText writeText; 18 FIleOutputStreamText readText; 19 StringBuffer contents = new StringBuffer(); 20 Scanner keyboard...
How can I write java program code that do reverse, replace, remove char from string without...
How can I write java program code that do reverse, replace, remove char from string without using reverse, replace, remove method. Only string method that I can use are length, concat, charAt, substring, and equals (or equalsIgnoreCase).
(java)Fix the code in this program. Fix lines, add lines… Comment each line that you fixed...
(java)Fix the code in this program. Fix lines, add lines… Comment each line that you fixed … what you did to fix it. import java.util.Scanner; public static void main(String[] args) { // This program Converts grade Points into a Letter grade. int gradePoints == 00; // Declare variable and assign initial value System.out.printl("Enter Grade Points: "; //Input gradePoints; if ( gradePoints >= -42 ) { System.out.println("Grade = A"); } // if true, then ends here, if false drop to next...
Can you fix this code please. the removing methods id no doing anything. this is java...
Can you fix this code please. the removing methods id no doing anything. this is java code import java.util.NoSuchElementException; public class DoublyLinkedList<E> {    public int size;    public Node head;    public Node tail;             @Override    public boolean isEmpty() {               return size == 0;    }    @Override    public int getSize() {               return 0;    }    @Override    public void addAtFront(E element) {       ...
The source code I have is what i'm trying to fix for the assignment at the...
The source code I have is what i'm trying to fix for the assignment at the bottom. Source Code: #include <iostream> #include <cstdlib> #include <ctime> #include <iomanip> using namespace std; const int NUM_ROWS = 10; const int NUM_COLS = 10; // Setting values in a 10 by 10 array of random integers (1 - 100) // Pre: twoDArray has been declared with row and column size of NUM_COLS // Must have constant integer NUM_COLS declared // rowSize must be less...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT