It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center
                            
                        
                    
                
                7年前关闭。
            
        

我试图了解多线程编程的概念。我知道死锁和互斥锁的概念,但是我找不到以下问题的答案。使用互斥锁时如何出现死锁问题?

最佳答案

这是如何在Java中引起deadlock的具体示例。我们产生两个线程。第一个获取a上的互斥锁,然后等待第二个,然后尝试获取b上的锁。第二个获取对b的锁定,然后等待,然后尝试获取a。结果是程序进入死锁并永远运行。

public class Deadlock {
    public static void main(String[] args) {
        final Object a = new Object();
        final Object b = new Object();
        new Thread() {
            @Override
            public void run() {
                synchronized (a) {
                    /* wait for a second to make it likely the other thread can acquire b */
                    try { Thread.sleep(1000); } catch (Exception e) {  }
                    synchronized (b) {
                        System.out.println("Acquired a, then b.");
                    }
                }
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                synchronized (b) {
                    /* wait for a second to make it likely the other thread can acquire a */
                    try { Thread.sleep(1000); } catch (Exception e) {  }
                    synchronized (a) {
                        System.out.println("Acquired b, then a.");
                    }
                }
            }
        }.start();
    }
}


请注意,不能保证此代码会进入死锁状态。线程调度程序完全有权在第一个线程上运行第一个线程直到完成,反之亦然。由于此示例中的等待时间很长,因此可以确定系统将进入死锁状态,但是如果不是休眠一秒钟,则两个线程在每次获取锁之前都对可变时间长度进行了一些计算,以下任何事情可能随机发生:


僵局
"Acquired a, then b.",然后是"Acquired b, then a."
"Acquired b, then a.",然后是"Acquired a, then b."


您如何防止这种情况发生?


尽可能避免使用线程。
每个线程不必在线程之间共享资源,而是让每个线程对自己的数据进行操作,并相互发送不可变的消息。
如果绝对必须使用共享资源,请最小化使用的互斥锁的数量。如果所有内容都在同一对象上同步,则只有一个互斥锁,并且不会发生死锁。
如果您绝对必须有很多互斥锁,并且线程需要获取它们的组合,请执行以下操作:编写一个定义锁总顺序的函数。然后,每当需要执行涉及多个互斥锁的操作时,请创建所涉及的互斥锁的列表,对它们进行排序,然后在操作开始时按排序顺序输入它们。


看一下java.util.concurrent包。它包含许多好东西,可以处理许多真正的毛茸茸的碎屑。

另外,我不能高估线程在意外位置切换的程度。一个常见的错误是逐行查看每个线程,并想像不同的方式行可以交错。但这还不够:线程可能会在某个库中深处的某些嵌套函数调用中间被切换出。

关于java - 与Java中的互斥锁有关的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12819676/

10-09 06:26
查看更多