Lambda表达式可以解决死锁吗?

时间:2017-09-19 02:28:34

标签: java multithreading lambda deadlock

我目前正在使用Java Deadlock Tutorial,并了解程序示例将始终遇到死锁。

public class Deadlock
    {
        private static class Friend
        {
            private final String name;
            public Friend(String name) { this.name = name; }

            public String getName() {return 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(){
                @Override
                public void run()
                {
                    alphonse.bow(gaston);
                }
            }).start();

            new Thread(new Runnable() {
                @Override
                public void run() {
                    gaston.bow(alphonse);
                }
            }).start();

        }
    }

当我用适当的lambda表达式替换其中一个Thread实例化时:new Thread(() -> gaston.bow(alphonse)).start(); 它似乎解决了死锁问题。但是当两个Thread实例化都被lambda替换时,程序再次陷入僵局。

这背后有原因吗?

1 个答案:

答案 0 :(得分:1)

测试中有一场比赛。如果两个线程同时bow,它只会死锁。

输出%s: %s has bowed to me!字符串所花费的时间足以在第一种情况下导致死锁,但是在引入实例化lambda类的额外时间时则不会。

通过在bow中引入延迟,可以在使用lambda时使测试死锁:

public synchronized void bow(Friend bower)
{
    System.out.format("%s %s: %s has bowed to me!%n", System.currentTimeMillis(), this.name, bower.getName());
    try {
        Thread.sleep(50);
    } catch (InterruptedException e) {
        // ignore
    }
    bower.bowBack(this);
}

...或者在开始测试之前通过实例化它:

public static void main(String[]args) throws InterruptedException {
    final Friend alphonse = new Friend("alphonse");
    final Friend gaston = new Friend("gaston");

    // instantiate the runner early
    Runnable gastonRunner = () -> gaston.bow(alphonse);

    new Thread(new Runnable(){
        @Override
        public void run()
        {
            alphonse.bow(gaston);
        }
    }).start();


    new Thread(gastonRunner).start();
}