Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么这不会导致死锁_Java_Deadlock_Synchronized - Fatal编程技术网

Java 为什么这不会导致死锁

Java 为什么这不会导致死锁,java,deadlock,synchronized,Java,Deadlock,Synchronized,为什么下面的代码不会导致死锁 从我对多线程编程的有限理解来看,当调用getBar1()时,sharedBuffer将被“锁定”,因此,当该方法尝试调用getBar2()时,线程将不得不等待sharedBuffer(由自身持有!)。换句话说,getBar2()无法返回,直到getBar1()完成(并释放了sharedBuffer)。但另一方面,getBar1()也无法返回,因为它正在等待getBar2()返回 ==>死锁。(但事实并非如此,这也是我感到困惑的原因) Java的监视器是递归的,这意味

为什么下面的代码不会导致死锁

从我对多线程编程的有限理解来看,当调用
getBar1()
时,
sharedBuffer
将被“锁定”,因此,当该方法尝试调用
getBar2()
时,线程将不得不等待
sharedBuffer
(由自身持有!)。换句话说,
getBar2()
无法返回,直到
getBar1()
完成(并释放了
sharedBuffer
)。但另一方面,
getBar1()
也无法返回,因为它正在等待
getBar2()
返回

==>死锁。(但事实并非如此,这也是我感到困惑的原因)


Java的监视器是递归的,这意味着同一线程可以多次获取相同的锁

从JLS()中:

线程t可以多次锁定特定监视器;每次解锁都会反转一次锁定操作的效果


当并发操作试图以不同的顺序锁定两个或多个资源时,会发生死锁,并且它们都被困在等待另一个锁定的资源

例如,线程T1和T2在资源R1和R2上同步:

  • T1在R1上同步
  • 调度程序决定T2应该运行
  • T2在R2上同步
  • T2尝试在R1上同步;它被迫等待T1释放锁
  • 调度程序发现T2无法继续运行,所以允许T1运行
  • T1尝试在R2上同步;它被迫等待T2释放锁
  • 两个线程都不能继续

这里所做的是基本的同步,一次只允许一个对象访问sharedBuffer。

它不会死锁,因为实际上只有一个锁。在这两个函数中,您都锁定了sharedBuffer。当第一个线程调用getBar1()时,它会锁定sharedBuffer。当同一个线程调用getBar2()时,它会命中synchronized块,并且已经有了锁,所以它只是进入了锁

public class Deadlock extends Thread
{
    private Deadlock other;
    private String name;

    public static void main(String[] args)
    {
        Deadlock one = new Deadlock("one");
        Deadlock two = new Deadlock("two");
        one.setOther(two);
        two.setOther(one);
        one.start();
        two.start();
    }

    public setOther(Deadlock other){ this.other = other; }

    public void run() {
       deadlock();
    }

    public synchronized deadlock() {
         System.out.println("thread " + this.name + " entering this.deadlock()");
         sleep(1000); // adjust as needed to guarantee deadlock
         System.out.println("thread " + this.name + " calling other.deadlock()");
         other.deadlock(this.name);
         System.out.println(name + " - deadlock avoided!");
    }
}
如果要导致死锁,请使用两个要锁定的不同值。然后,只有在计时正确的情况下,你才能看到它。如果要强制死锁,请确保第一个线程休眠足够长的时间,以便第二个线程获得锁

下面是一些将死锁的代码。。。(未经测试,prolly有打字错误)。这应该是可行的,因为与需要锁的线程不同的线程具有锁

public class Deadlock extends Thread
{
    private Deadlock other;
    private String name;

    public static void main(String[] args)
    {
        Deadlock one = new Deadlock("one");
        Deadlock two = new Deadlock("two");
        one.setOther(two);
        two.setOther(one);
        one.start();
        two.start();
    }

    public setOther(Deadlock other){ this.other = other; }

    public void run() {
       deadlock();
    }

    public synchronized deadlock() {
         System.out.println("thread " + this.name + " entering this.deadlock()");
         sleep(1000); // adjust as needed to guarantee deadlock
         System.out.println("thread " + this.name + " calling other.deadlock()");
         other.deadlock(this.name);
         System.out.println(name + " - deadlock avoided!");
    }
}

阅读有关重入锁的信息。Java中本机的是。啊,所以
getBar1()
正在访问
sharedBuffer
这一事实并不能阻止它调用
getBar2()
,它也将访问
sharedBuffer
?但是如果其他线程试图调用
getBar2()
,它将阻塞,直到这一次调用完成为止?@onetwotree:是的。Okie,知道了。谢谢我只是不知道“一个线程可以多次获得相同的锁”。这很有帮助!!:)