【问题标题】:How many threads are involved in deadlock [duplicate]死锁涉及多少个线程[重复]
【发布时间】:2015-07-14 07:28:32
【问题描述】:

我正在尝试找出面试问题的答案 死锁涉及多少线程

我回答应该是两个或更多,但面试官说这是一个错误的答案。

我尝试在网上搜索,但不明白为什么我的答案是错误的

【问题讨论】:

  • 面试官通常不会告诉你你是否正确回答了一个问题(因为它会降低候选人的积极性)。如果他们确实告诉了你,那么他们应该向你解释为什么它是错误的。据你所知,面试官本人并不知道答案。
  • 愚蠢的面试问题。活性失效可以采取许多不同的形式。哪些称“死锁”或哪些称“死锁”并不重要。一个更好的问题是请您描述它是如何发生的。

标签: java multithreading


【解决方案1】:

如果线程试图获取它已经拥有的资源,它可能会死锁。想象一个持有数据库锁的线程,然后切换到另一个事务(不提交第一个事务)并尝试再次获取相同的锁。

【讨论】:

  • 这不是通常所说的“死锁”。 Wikipedia 说:在并发编程中,死锁是指两个或多个相互竞争的动作都在等待对方完成的情况,因此永远都不会。
  • 我不确定“竞争行为”是否一定意味着不同的线程。在我的示例中,您只是在同一个线程中有一个未完成的操作。也许对 interwiew 问题的正确答案应该以“这取决于死锁的定义”开头;-)
  • 这完全取决于问题的上下文。面试官问的是多线程还是数据库事务?上下文很重要。我的猜测是,面试官问了一个非常笼统的问题,并希望被面试者给他解决他前一周遇到的特定错误的解决方案,并花了几天时间才弄清楚。
【解决方案2】:

显而易见的答案是“两个或更多”,因为您可能拥有导致死锁的依赖链。

1 locks A
2 locks B
3 locks C
3 requests A
2 requests C
1 requests B

如果您想检查被锁定的资源不是由线程“拥有”而是由另一个资源“拥有”的情况,它们可能意味着“一个或多个”。

如果资源的拥有对象不是线程,则需要多次出现拥有对象而不是线程才能导致死锁。在上面的示例中,1、2 和 3 拥有资源而不是线程。

您可以想到各种情况,其中资源 (A) 也锁定了资源 (B),然后同一个线程请求资源 (B) 但无法获取它。但是,我真的不认为使用“死锁”这个词会有帮助。

【讨论】:

  • 直接引用问题:“我回答应该是两个或更多,但面试官说这是一个错误的答案。”
【解决方案3】:

答案是取决于锁的种类或锁定机制。

  • 对于可重入锁,您需要两个或更多线程。 (请注意,Java 原始锁/互斥锁是可重入的)。

  • 对于不可重入锁,单个线程可以通过尝试获取它已经持有的锁来使自己死锁1

线程也有可能以与死锁2几乎无法区分的其他方式阻塞自身。例如:

    Thread.currentThread().join();

将阻塞一个线程,让它等待直到它完成。在后台,join() 呼叫正在等待一个永远不会发生的通知/条件。您可以自己明确地做同样的事情;例如

    Object lock = new Object();  // local variable
    synchronized (lock) {
        lock.wait();
    }

1 - 这取决于锁的精确语义。例如,在这种情况下,可以实现一个不可重入锁来抛出异常而不是死锁。

2 - 这是否实际上是死锁取决于您对术语“死锁”使用的精确定义。不建议在求职面试中就术语争论不休!

【讨论】:

    【解决方案4】:

    至少在 Java 中,看起来线程无法锁定自身(就像在递归中一样);但另一个线程可以;所以答案必须是必须有两个线程;这是一个例子:

    package threadLockTest;
    
    public class ThreadLocking {
    
    private Object LOCK = new Object();
    
    public void recursionWithSynchronization (int count) {
        System.out.println("inside recursionWithSynchronization: count: " + count);
        synchronized (LOCK) {
            if (count == 10) {
                return;
            } else {
                try {
                    Thread.sleep(500);
                    recursionWithSynchronization((count+1));
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
    
    public static void main (String... args) {
        System.out.println("starting Main thread");
        ThreadLocking stli = new ThreadLocking();
        Runnable ry = () -> {
            System.out.println("starting thread");
            stli.recursionWithSynchronization(1);
            System.out.println("ending thread");
        };
        Thread t1 = new Thread(ry);
        Thread t2 = new Thread(ry);
        t1.start();
        t2.start();
        System.out.println("ending Main thread");
    }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 2020-11-24
      • 1970-01-01
      • 2018-06-16
      • 1970-01-01
      • 1970-01-01
      • 2016-01-28
      • 1970-01-01
      相关资源
      最近更新 更多