类级别锁定未按预期工作

时间:2017-05-25 05:57:51

标签: java synchronization

我写了一个以下的程序,根据我的理解它不应该打印

'Didn't hang, it should've.因为shouldHang方法是静态同步的,我已经进行了类级锁定。

我无法理解这种行为。有人可以帮我解决这个问题,

public class Test1 {
        synchronized static public void shouldHang() {
            System.out.println("Didn't hang, it should've.");
        }

        static public void main(String args[]) {
            Test1 test = new Test1();
            synchronized (test.getClass()) {
                new Thread(new trylock()).start();
            }

        }
    }

    class trylock implements Runnable {
        public void run() {
            Test1.shouldHang();
        }
    }

4 个答案:

答案 0 :(得分:4)

为什么不打印呢?您有一个线程调用单个同步方法。调用方法时,主线程已完成执行(因此释放了锁)。启动一个线程只是启动它并立即返回,所以事件的顺序是:

  1. 主线程获取锁
  2. 主线程启动另一个线程
  3. 主线程释放锁(并停止运行)
  4. 第二个帖子获取锁
  5. 第二个帖子打印
  6. 第二个线程释放锁定(并停止运行)
  7. 第二个线程可能尝试获取锁,而主线程仍然拥有它,但这不会改变任何东西:主线程释放它,从而使它可用于第二个线程。

答案 1 :(得分:1)

您的主线程在try-lock线程的整个生命周期内都没有锁定。你需要让主线程等待。然后你就会陷入僵局。这就是你想要的吗?

synchronized (test.getClass()) {
    Thread t = new Thread(new trylock());
    t.start();
    t.join(); // Now the thread hang, but of course this will only deadlock your program.
}

答案 2 :(得分:0)

Thread.start启动给定的线程,然后立即返回;它不会等待新启动的线程完成。

在这种情况下,新线程会启动并被阻止,正如您所说;但是之后,主线程从start()方法返回并且synchronized块竞争,解除阻塞新线程并让它打印它的消息。

答案 3 :(得分:0)

为什么不打印?您的主线程仅使用锁来创建和启动第二个线程,然后释放锁。然后第二个线程获取锁并执行该方法。请注意,第二个线程可能确实在等待“非常微不足道”的时间,因此您没有看到它。

如果你真的想在这里看到 synchronized 的行为,请在你的线程起始块之后添加一个5秒的小睡眠。