为什么我们需要一个可重入的锁?

时间:2013-08-14 16:57:28

标签: multithreading reentrantlock

我(有点)了解jdk 5 ReentrantLock here

的功能

但为什么我们想要'重入'锁?即如果一个线程已经锁定了一个对象,为什么还需要再次获取它呢?

2 个答案:

答案 0 :(得分:3)

考虑这个理论示例:您正在使用锁来保护某些后端数据,同时更新GUI中列表框中的某些项目。您循环并修改项目。执行此操作时,列表框将触发您已注册处理程序的事件(可能是Selection Changed事件或其他事件)。此处理程序还锁定相同的锁以处理新项。如果锁不是递归的,则该线程将在第二次尝试获取锁时死锁。

答案 1 :(得分:2)

当资源不能容忍所有形式的任意定时访问,但是可以容忍嵌套执行上下文中可能发生的某些访问模式时,重入锁很有用。在许多情况下,它们的使用是不美观和草率的,但是可能更容易安排事情,以便保证重入锁定的工作比安排事情以便使一个人不必要。

请注意,虽然许多语言默认使锁可重入,但这不一定是好事。如果代码获取了一个锁,然后该线程中的其他代码尝试获取同一个锁的令牌,那么很明显,让第二个请求等到锁被释放后,这将不会非常有效。但是,这并不意味着第二个请求应该允许访问锁。在许多情况下,正确的行动方案是第二个请求抛出一个立即异常(在释放锁之前不应该授予访问权限,并且在请求被授予之前不会发生(不应该发生)或者代码以其他方式退出(异常是最自然的选择)。如果修改锁定保护数据结构的方法称为某些外部代码而不希望使用数据结构,则会出现这种情况。当数据结构处于不一致的状态时。如果代码意外地尝试使用数据结构,让它立即失败并发生异常可能比让它永远等待锁定更好,但它永远不会得到,或者快速地进入锁定并访问无效数据。

在许多情况下,当受保护的资源满足某些但不是所有的不变量时,代码将调用嵌套例程,并且外部代码可能希望嵌套例程对其进行某些更改而不是其他更改。在这种情况下,重入锁可能是合适的,但需要注意确保代码不会执行它不应该执行的操作。重入锁定的一个优点是,如果使用锁定进行嵌套调用的代码设置标志以指示其promise / requirements,并且获取锁定的代码在条目上测试这些标志,则可以保证仅在可预测的情况下操纵标志序列。如果两个不同的线程同时尝试使用资源,那么这样的事情是不可能的。