为什么在这个程序中同一个对象没有死锁 - Java多线程

Ven*_*ata 2 java multithreading synchronized

我下面有三节课.Main,两个线程和Obj,其方法是同步的

public class DeadLocks {

    public static void main(String[] args) {
        SyncObj so = new SyncObj();
        ThreadObj to = new ThreadObj(so);
        ThreadObj1 to1 = new ThreadObj1(so);

        to.start();
        to1.start();
    }
}

class SyncObj {
    synchronized void foo() {
        System.out.println("Foo Started");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        bar();
    }

    synchronized void bar() {
        System.out.println("bar started");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        foo();
    }

}

class ThreadObj1 extends Thread {
    SyncObj so;

    public ThreadObj1(SyncObj so) {
        this.so = so;
    }

    @Override
    public void run() {
        so.bar();
    }
}

class ThreadObj extends Thread {
    SyncObj so;

    public ThreadObj(SyncObj so) {
        this.so = so;
    }

    @Override
    public void run() {
        so.foo();
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我在同一个对象上调用synchronized方法.这两种方法都在同时执行和调用.没有死锁情况.谁有人解释为什么?抱歉这个愚蠢的问题.

Kha*_*111 6

据我所知,你在so两种情况下使用相同的对象().所以没有死锁的情况.您需要锁定两个或多个对象,其中每个关键部分需要锁定而不是它所持有的锁定.另一个锁由"另一个"线程持有.

令人困惑,这将启发:" https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html "

您将never ever deadlock在您描述的场景中.在这种情况下,只有一个so正在共享并正在与之同步.

让我举个例子来说明:

假设Andy和Sandy正在玩两个足球B1B2.

现在进一步假设Andy和Sandy分别拥有球B1B2.例如安迪有球B1和桑迪有球B2.

现在他们设计了一个游戏,他们每个都需要两个球.现在Sandy也想要球B1,同时,Andy想要B2.

他们俩都无法放弃他们所拥有的球.安迪不会放弃B1,反之亦然.

So both of them cannot continue and are stuck. We call this a deadlocked situation.
Run Code Online (Sandbox Code Playgroud)

希望这个例子有帮助.你可以利用你的想象力将比赛中的球数增加到3或4(依此类推......)和/或增加球员数量.


das*_*ght 5

你没有陷入僵局,因为你的程序不符合形成它的四个必要条件中的两个:

  • 相互排斥 - 是的,
  • 坚持部分分配 - 不,
  • 没有先发制人 - 是的,
  • 循环依赖 - 没有

您需要至少两个资源"A"和"B"才能形成死锁.一个线程应该抓住"A"并尝试抓住"B",而另一个应抓住"B",并尝试抓住"A".


小智 5

我不确定你为什么会在这里遇到僵局.确实,只有一个对象可以访问同步部分,但是它可以根据需要进行访问.您可以修改代码以使其清晰:

public class DeadLocks {

     public static void main(String[] args) {
         SyncObj so = new SyncObj();
         ThreadObj to = new ThreadObj(so);
         ThreadObj1 to1 = new ThreadObj1(so);

         to.start();
         to1.start();
     }
 }

 class SyncObj {
     synchronized void foo(String msg) {
         System.out.println("Foo Started: " + msg);
         try {
             Thread.sleep(1000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         bar(msg);
     }

     synchronized void bar(String msg) {
         System.out.println("bar started: " + msg);
         try {
             Thread.sleep(1000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         foo(msg);
     }

 }

 class ThreadObj1 extends Thread {
     SyncObj so;

     public ThreadObj1(SyncObj so) {
         this.so = so;
     }

     @Override
     public void run() {
         so.bar("TO1");
     }
 }

 class ThreadObj extends Thread {
     SyncObj so;

     public ThreadObj(SyncObj so) {
         this.so = so;
     }

     @Override
     public void run() {
         so.foo("TO");
     }
 }
Run Code Online (Sandbox Code Playgroud)

您可以看到以下输出:

Foo Started: TO
bar started: TO
Foo Started: TO
bar started: TO
Foo Started: TO
bar started: TO
Run Code Online (Sandbox Code Playgroud)

你可以认为'synchronized'意味着锁定(this),其中'this'是一个SyncObj实例.因此,只有一个锁,并且不可能获得死锁.