1

我在这里了解(有点)jdk 5 ReentrantLock 的功能

但是为什么我们想要一个“重入”锁呢?即如果一个线程已经拥有一个对象的锁,为什么它需要再次获取它?

4

2 回答 2

3

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

于 2013-08-14T17:02:54.610 回答
2

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

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

在许多情况下,当受保护的资源满足其部分但不是全部的不变量时,代码会调用嵌套例程,并且外部代码可能期望嵌套例程对其进行某些更改,但对其他例程不进行更改。在这种情况下,可重入锁可能是合适的,但需要注意确保代码不会做不应该做的事情。可重入锁的一个优点是,如果在持有锁的情况下进行嵌套调用的代码设置标志以指示其承诺/要求,并且获得锁的代码在进入时测试这些标志,则可以保证这些标志只会在可预测的情况下被操纵序列。如果两个不同的线程试图同时使用资源,这样的事情是不可能的。

于 2013-08-14T17:35:59.583 回答