简体   繁体   中英

Alternative to solve the DeadLock in java

I am reading Java Concurrency Tutorial from Oracle.

And there is an example of the DeadLock

Core code:

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

And then when the tutorial goes to the LockObject , it provide a solution to handle the deadlock by the Lock Object .

Now I wonder if there is an alternative method to avoid the deadlock without using the Lock Object?

One way of avoiding a deadlock is breaking the symmetry by imposing an order in which the two locks are acquired. For example you may say that when initiating a bow the thread should always put a lock on the friend whose name comes first in alphabetic order, so that any thread doing a bow must acquire the lock on Alphonse first and then the lock on Gaston, never in reverse:

    public void bow(Friend bower) {
        Friend lock = (this.name.compareTo(bower.name)<0)? this : bower);
        synchronized (lock) {
            System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName());
            bower.bowBack(this);
        }
    }
    public void bowBack(Friend bower) {
        Friend lock = (this.name.compareTo(bower.name)>0)? this : bower);
        synchronized (lock) {
            System.out.format("%s: %s has bowed back to me!%n", this.name, bower.getName());
        }
    }

A lock-free option is using an atomic variable to signal if a bow is already in progress, and wait if there is one:

    private static AtomicBoolean bowing = new AtomicBoolean();
    public void bow(Friend bower) {
        while (!bowing.compareAndSet(false, true)) Thread.yield();

        System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName());
        bower.bowBack(this);

        bowing.set(false);
    }

Yet another way of avoiding deadlock is using a single lock instead of two; two threads competing for a single lock cannot deadlock.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM