2017-01-14 21 views
2

如果我有一个来自同步块的返回语句,我对释放锁的点感到困惑;发现我已经添加了try-finally块并在最终阻止打印中添加了一个sysout'lock released',但是我可以清楚地看到,即使在'release'语句被打印之前,第二个线程已经获得了锁定。锁何时释放?什么是保证事情不会变得混乱?如果我从同步块返回,锁何时释放?

public static int testClassLevelMonitor() throws InterruptedException { 
    try { 
    synchronized(TestLocks.class) { 
     System.out.println("Static Block : Thread " + Thread.currentThread().getName() + " -- have the lock"); 
     Thread.currentThread().sleep(1000); 
     return 0; 
    } 
    } finally { 
     System.out.println("Static Block : Thread " + Thread.currentThread().getName() + " -- released the lock"); 
     System.out.println("\n\n"); 
    } 
} 

静态块:线程池1线程1 - 有锁

静态块:线程池1线程2 - 有锁

静块:线程池1线程1 - 释放锁

静态块:线程池1线程2 - 释放锁

+2

一旦它保护的区块完成,就可以释放锁定,这意味着在返回之后但在最终区块之前。这并不意味着如果jvm认为它会提高性能,则不允许jvm保持更长的锁定时间。 – Voo

+1

当一个线程到达'finally'块时,它释放了锁。这时你不会考虑事件的顺序。下一个线程可能会获取该锁并首先从同步块打印其输出;或者第一个线程可能首先从“finally”块打印它的消息。您无法提前知道订单。 –

+0

你还没有发布'TestLocks.java'以及你如何创建'thread-1'和'thread-2'?我最强烈的怀疑是'testClassLevelMonitor()'synchronized方法获取了正在运行该方法的对象的锁定,但有两个不同的线程对象调用它。 – fabfas

回答

2

​​声明在Java Language Specification中指定。

SynchronizedStatement: 
    synchronized (Expression) Block 
  • [..]
  • 否则,让Expression的非空值是V。正在执行的线程锁定与V关联的监视器。然后Block 被执行,然后有一个选择:
    • 如果Block的执行正常完成,然后将显示器解锁和​​语句正常完成。
    • 如果Block的执行出于任何原因突然完成,然后将显示器解锁并且​​语句completes abruptlyreturn突然完成)出于同样的原因。

换句话说,锁只举办了​​语句体的长度。

System.out.println("Static Block : Thread " + Thread.currentThread().getName() + " -- have the lock"); 
Thread.currentThread().sleep(1000); 
return 0; 

finally块将在没有保持锁的情况下执行。


在占用锁时,执行的线程将推动评估return语句到堆栈的结果,释放锁,执行finally块,然后返回该值。