线程 – 为什么锁定必须遵循try和finally

锁总是后跟一个try / finally块,为什么?

ReentrantReadWriteLock readWriteLockBitmap = new ReentrantReadWriteLock(); Lock read = readWriteLockBitmap.readLock(); Lock write = readWriteLockBitmap.writeLock(); int shared = 0; public void function1(){ read.lock(); try{ //reading shared int } finally{ read.unlock(); } } public void function 2(){ write.lock(); try{ //modify shared int } finally{ write.unlock(); } } 

为什么有这个try / finally块而不是简单地编写代码如下:

 ReentrantReadWriteLock readWriteLockBitmap = new ReentrantReadWriteLock(); Lock read = readWriteLockBitmap.readLock(); Lock write = readWriteLockBitmap.writeLock(); int shared = 0; public void function1(){ read.lock(); //reading shared int read.unlock(); } public void function 2(){ write.lock(); //modify shared int write.unlock(); } 

如果出现任何问题(exception被抛出等),你想确保锁定被释放,无论如何。 这只是标准做法,即使在这种情况下在技术上可能是不必要的。

因为try / finally块是保证一段代码在另一段完成后执行的唯一方法。

你问为什么不这样做:

 public void function1(){ read.lock(); this.getSharedInt(); read.unlock(); } 

this.getSharedInt()抛出exception时会发生什么? 然后你的read.unlock()行不会被执行,导致程序死锁。 当然,它可能100%经过认证, 现在不会抛出exception,但是当您重构将共享int存储在文件或数据库中时会发生什么?

最后,不要忘记try / finally还会考虑错误,即使函数保证不抛出任何exception,运行时几乎可以在程序的任何一行抛出错误。

请注意,此代码也可以使用,但它会吞下exception。 finally使用finally允许exception正常传播,同时在所有条件下仍然可以解锁。

 public void function2(){ read.lock(); try { this.getSharedInt(); } catch(Throwable t) {} read.unlock(); } 

所以这样的事情不会发生:

 private static ReentrantReadWriteLock readWriteLockBitmap = new ReentrantReadWriteLock(); private static Lock read = readWriteLockBitmap.readLock(); private static Lock write = readWriteLockBitmap.writeLock(); private static int shared = 0; public static void function1() { read.lock(); somethingThatMightThrowAnException(); read.unlock(); } private static void somethingThatMightThrowAnException() { throw new RuntimeException("I'm a bad man."); } public static void function2() { write.lock(); //modify shared int write.unlock(); } public static void main(String[] args) { try { function1(); } catch (Exception e) { System.out.println("Got an exception, but so what?"); } function2(); } 

问题不在于您需要try块。 关键是要确保如果你的应用程序抛出了仍然调用解锁的任何类型的exception。 否则,锁将保持锁定状态。

为了确保无论发生什么,即使抛出exception,您仍然可以在离开方法之前解锁锁定的流。

http://www.google.co.uk/#sclient=psy&hl=en&q=java+Why+a+Lock+has+to+be+followed+by+try+and+finally+%3F

第一个命中是: http : //download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/locks/Lock.html

引用关键部分:

在大多数情况下,应使用以下习语:

  Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); } 

当锁定和解锁发生在不同的范围内时,必须注意确保在保持锁定时执行的所有代码都受try-finally或try-catch保护,以确保在必要时释放锁定。