对 ReentrantLock 在 Java 中的工作原理感到困惑

问题描述 投票:0回答:1

查看 javadoc 中

Condition
的示例注释。 来源

假设这种情况:

  1. Thread-1 在空缓冲区上调用 take()
  2. Thread-2 在空缓冲区上调用 put(1)

时间轴:

  1. 在 t0,Thread-1 在第 24 行获取锁

  2. 在t1,由于count==0进入L27忙等待 根据 javadoc 此时,线程释放锁并进入休眠状态。

  3. 在 t2 时,Thread-2 获取第 10 行 put 中的锁

  4. 在 t3 处,线程执行到第 17 行,这向 Thread-1 发出信号

由于 Thread-2 从未达到释放其锁的程度(第 19 行),因此在时间 t3 时发生了什么,Thread-1 可以执行吗?这会破坏一次只允许一个线程执行 ReentrantLock 的约定吗?

1 class BoundedBuffer<E> {
2    final Lock lock = new ReentrantLock();
3    final Condition notFull  = lock. newCondition(); 
4    final Condition notEmpty = lock. newCondition(); 
5 
6    final Object[] items = new Object[100];
7    int putptr, takeptr, count;
8 
9    public void put(E x) throws InterruptedException {
10      lock. lock();
11      try {
12        while (count == items. length)
13          notFull. await();
14        items[putptr] = x;
15        if (++putptr == items. length) putptr = 0;
16        ++count;
17        notEmpty. signal();
18      } finally {
19        lock. unlock();
20      }
21    }
22 
23    public E take() throws InterruptedException {
24      lock. lock();
25      try {
26        while (count == 0)
27          notEmpty. await();
28        E x = (E) items[takeptr];
29        if (++takeptr == items. length) takeptr = 0;
30        --count;
31        notFull. signal();
32        return x;
33      } finally {
34        lock. unlock();
35      }
36    }
37  }

java multithreading concurrency locking
1个回答
0
投票

不,当在 ReentrantLock

 上阻塞的线程收到信号时,不会违反 
await()
 的互斥保证。这样的线程在重新获取锁之前无法从 
await()
返回,而在任何给定时间只有一个线程可以持有该锁。换句话说,有信号线程最早可以从
await()
返回,就在调用
signal()
的线程释放锁之后。


文档

条件#await()

导致当前线程等待,直到收到信号或中断。

与此

Condition
关联的锁被原子释放,当前线程出于线程调度目的而被禁用,并处于休眠状态,直到发生以下四种情况之一:

其他线程调用了该
    signal()
  • Condition
    方法,并且当前线程恰好被选为要唤醒的线程;或
    其他一些线程为此 
  • signalAll()
  • 调用
    Condition
    方法;或
    其他线程中断当前线程,支持线程挂起中断;或
  • 发生“
  • 虚假唤醒
  • ”。
  • 在所有情况下,
在此方法可以返回之前,当前线程必须重新获取与此条件相关的锁

[强调]。当线程返回时,保证持有这个锁。

[...]

条件#signal()

唤醒一个等待线程。

如果有任何线程在此条件下等待,则选择一个线程进行唤醒。该线程

必须重新获取锁,然后才能从

await

 
[强调已添加]

[...]

© www.soinside.com 2019 - 2024. All rights reserved.