【问题标题】:Handle multiple tryLock() calls with a thread使用线程处理多个 tryLock() 调用
【发布时间】:2018-03-24 17:46:17
【问题描述】:

作为线程间同步的一种方法,在Java中我们可以使用ReentrantLock类。它有一个名为tryLock() 的方法,如果它注意到尚未获取线程,则允许线程不等待。由于它返回一个布尔值,它可以与if 语句结合,使线程在无法获取锁的情况下执行其他操作,类似于:

if (lock.tryLock()) {
    // Do things inside the lock
    lock.unlock();
} else {
    // The lock was occupied, do other things
}

在那之前一切都很好。但是,假设我们有两个(或更多)锁,并且我们希望在进入临界区之前获得它们。在某些特定情况下,第一个锁可用,但第二个锁不可用。为了让这个场景正常工作,我想出了一些可供选择的选项。请注意,我更担心锁的解锁,而不是它们的锁定:

// Option 1
if (lock1.tryLock() && lock2.tryLock()) {
    // Congratulations! You are inside both locks
} else {
    // How to know if you got a lock, and if so, which one?
    // You will need to "blindly" unlock both
    try {
        lock1.unlock();
        lock2.unlock();
    } catch (IllegalStateMonitorException e) {
        // Thrown when you unlock a lock which is not yours
    }
}

在我的实现中,第一个选项基本上忽略了一个异常,这可能会在执行中的某个时间点导致问题。

// Option 2
if (lock1.tryLock()) {
    if (lock2.tryLock()) {
        // Congratulations! You are inside both locks
        // Do things
        lock2.unlock();
    }
    lock1.unlock();
}

第二个选项利用了这样一个事实,即可能没有获得第二个锁,但获得了第一个锁。我发现这更高效、更直观。

你认为哪个选项最好?您对此主题有更好的实现吗?

【问题讨论】:

标签: java concurrency synchronization reentrantlock


【解决方案1】:

只使用第二种变体。第一个会导致问题,例如当第二个锁被另一个线程持有时。它也不会以正确(反向)的顺序解锁。

【讨论】:

  • 我就是这么想的。所以这是处理这种情况的完全正确的方法,对吧?我的意思是,通过我没有考虑到的 Lock 方法,有没有更好的替代方法?
  • 除了您可能想在每次成功锁定后添加一些 try/finally 块以确保解锁之外,我想不出更好的方法。
  • 确实,我知道 try/finally 机制,但我想缩短代码。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-29
  • 2017-01-27
  • 2020-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
相关资源
最近更新 更多