How do I fix this deadlock code in java?

I have deadlock code codes from oracle.

class Thread_Test {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
       public synchronized void bow(Friend bower) {
            System.out.format("%s: %s" + "  has bowed to me!%n", this.name, bower.getName());

            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s" + " has bowed back to me!%n", this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse = new Friend("Alphonse");
        final Friend gaston = new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}

      

If I change the bow function like below, I can solve the deadlock problem.

public void bow(Friend bower) {
    synchronized(this) {
        System.out.format("%s: %s" + "  has bowed to me!%n", this.name, bower.getName());
    }
    bower.bowBack(this);
}

      

Can I use other approaches to solve this deadlock problem.

Specifically, I'm wondering what Thread.sleep () might be a solution to the deadlock and how I can use it.

Could you please inform me about the possibility of Thread.sleep () and other approaches?

Thank you so much

+3


source to share


2 answers


The deadlock occurs because the following method calls are occurring:

  • Alphonse summons the bow (), gaining the Alphonse / Bow block.
  • Gaston calls onion (), getting gaston / onion.
  • Alphonse tells Gaston that he bowed () and waits for Gaston to complete this action.
  • Gaston tells Alphonse bowBack () and waits for Alphonse to complete this action.
  • thus both wait for the other to finish bowBack () to finish their bow (), but cannot start their own bowBack () until they finish bow (). Dead end.

The reason for your solution is because the call to bowBack (this) is outside of the synchronized block.



Intelligent use of locks can both more clearly demonstrate why and exactly where deadlock occurs, and can prevent it. Java Semaphore class is nice looking.

To fix this (prevent deadlock, but keep it streamed) you need to expand on the problem - what should happen when Gaston waits for Alphonse to complete bow () to execute his own bow (), but Alphonse Lawn has to execute bowBack ( ) to finish? One smart solution is that Gaston refuses to execute the bow () when the bowBack () call comes in and just does the bowBack () function, but it all depends on what problem you are trying to solve.

+1


source


You need to block 2 objects at once (call them A

and B

). here is a good explanation of what might happen. To fix this, you can try to always block in the same order:

static class Friend {
    private static int idCounter;
    private final int id;
    private final String name;

    public Friend(String name) {
        this.name = name;
        id = idCounter++;
    }
    public String getName() {
        return this.name;
    }

    public void bow(Friend bower) {
        Friend first, second;
        if(bower.id > id) {
            first = this;
            second = bower;
        } else {
            first = bower;
            second = this;
        }
        synchronized(first) {
            synchronized(second) {
                System.out.format("%s: %s has bowed to me!%n", this.name,bower.getName());

                bower.bowBack(this);
            }
        }
    }
    public synchronized void bowBack(Friend bower) {
        System.out.format("%s: %s has bowed back to me!%n", this.name, bower.getName());
    }
}

      



Here, the one Friend

with the lower id is blocked first, so now no deadlock should happen.

0


source







All Articles