java condition.await()直到其锁定呼叫Unlock()才发出信号()
Java Doc for condition.await()
:
与此情况关联的锁被原子释放,并且 当前线程被禁用于线程调度目的,并且 处于休眠状态,直到四件事发生:
- 其他一些线程调用
信号
此条件的方法...
我写了一个测试程序,以查看,thread-1呼叫之后并被阻止,thread-2呼叫code> condition.signal()
。
我希望Thread-1应立即从等待()
返回并继续。
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.*;
public class TestThreadCondition {
public static void main(String[] args) throws InterruptedException {
Lock rLock = new ReentrantLock();
Condition cond = rLock.newCondition();
AtomicBoolean aBool = new AtomicBoolean(true);
Thread t1 = new Thread(new Runnable() {
@Override public void run() {
try {
rLock.lock();
System.out.println("(Step 1) Thread 1 locks and sleeps 1s");
Thread.sleep(1000);
while (aBool.get()) {
System.out.println("(Step 3) Thread 1 enters while loop");
cond.await();
System.out.println("(Step 5) Thread 1 got signal");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override public void run() {
try {
Thread.sleep(300);
System.out.println("(Step 2) Thread 2 also requires lock, blocked");
rLock.lock();
System.out.println("(Step 4) Thread 2 gets lock after thread 1 cond wait, sends signal");
cond.signal(); // I hope this would signal "t1" and t1 will enter (Step 5) immediately.
System.out.println("(Step 6) Thread 2 sleeps 3s and set aBool");
Thread.sleep(3000);
aBool.compareAndSet(true, false);
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
System.out.println("(Step 7) unlock");
}
}
});
t2.start();
t1.join();
t2.join();
}
}
我期望该程序将运行和打印,
Step1->Step2->Step3->Step4->Step5->Step6->Step7.
但实际结果是:
(Step 1) Thread 1 locks and sleeps 1s
(Step 2) Thread 2 also requires lock, blocked
(Step 3) Thread 1 enters while loop
(Step 4) Thread 2 gets lock after thread 1 cond wait, sends signal
(Step 6) Thread 2 sleeps 3s and set aBool
(Step 7) unlock
(Step 5) Thread 1 got signal
步骤5 是在 step6 之后执行的。和 step7 。在Thread-1,cond.await()
中,当Thread-2称为cond.signal
时,它都不会唤醒,并且它会阻止thread-thread-2 nater-2 nater-nater-2 nater-thread-2 nater-nater-2 nater-2 nater-2 nater-nater-2 > rlock.unlock()。
正如我一开始所说,这似乎与Javadoc的解释冲突。如何了解我的代码的行为?
Java doc for Condition.await()
:
The lock associated with this Condition is atomically released and the
current thread becomes disabled for thread scheduling purposes and
lies dormant until one of four things happens:
- Some other thread invokes the
signal
method for this Condition...
I wrote a test program to see, after Thread-1 calls Condition.await()
and gets blocked, Thread-2 calls Condition.signal()
.
I expect Thread-1 should return immediately from await()
and continue.
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.*;
public class TestThreadCondition {
public static void main(String[] args) throws InterruptedException {
Lock rLock = new ReentrantLock();
Condition cond = rLock.newCondition();
AtomicBoolean aBool = new AtomicBoolean(true);
Thread t1 = new Thread(new Runnable() {
@Override public void run() {
try {
rLock.lock();
System.out.println("(Step 1) Thread 1 locks and sleeps 1s");
Thread.sleep(1000);
while (aBool.get()) {
System.out.println("(Step 3) Thread 1 enters while loop");
cond.await();
System.out.println("(Step 5) Thread 1 got signal");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override public void run() {
try {
Thread.sleep(300);
System.out.println("(Step 2) Thread 2 also requires lock, blocked");
rLock.lock();
System.out.println("(Step 4) Thread 2 gets lock after thread 1 cond wait, sends signal");
cond.signal(); // I hope this would signal "t1" and t1 will enter (Step 5) immediately.
System.out.println("(Step 6) Thread 2 sleeps 3s and set aBool");
Thread.sleep(3000);
aBool.compareAndSet(true, false);
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
System.out.println("(Step 7) unlock");
}
}
});
t2.start();
t1.join();
t2.join();
}
}
I expected that this program will run and print
Step1->Step2->Step3->Step4->Step5->Step6->Step7.
But the actual result was:
(Step 1) Thread 1 locks and sleeps 1s
(Step 2) Thread 2 also requires lock, blocked
(Step 3) Thread 1 enters while loop
(Step 4) Thread 2 gets lock after thread 1 cond wait, sends signal
(Step 6) Thread 2 sleeps 3s and set aBool
(Step 7) unlock
(Step 5) Thread 1 got signal
The Step 5 was executed after Step6 and Step7. It looks like that in Thread-1, cond.await()
was not awaken when Thread-2 called cond.signal
, and it blocks until Thread-2 called rLock.unlock()
.
This seems conflicts with the Javadoc's explanation, as I stated at the beginning. How to understand the behavior of my code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在您的代码打印时,
Thread1已经退出了等待方法。如果没有已经获得锁定,就不可能走那么远。因此,如果另一个线程仍然有锁定,那自然不会发生。
因此,您的代码不是一个很好的测试,我们不知道信号是否已延迟到锁定为止,或者信号是否比该信号更早发生,并且thread1被唤醒,但正在阻止锁定。
在与内在锁的可比较情况下,它在Apidoc中拼写出来,该锁定通知将延迟,直到通知线程释放其锁定为止。无论如何,等待线程直到那时才能采取行动。如果在这里发生同样的情况,那就不足为奇了。
在任何情况下,爪哇省都没有矛盾,醒来并获得锁定是两种不同的事情。
At the time your code prints
Thread1 has already exited the await method. It cannot have gotten that far without already having acquired the lock. So naturally that can't happen if another thread still has the lock.
So your code isn't a good test, we don't know from it whether the signal was delayed until the lock was released, or if the signal occurred earlier than that and thread1 was woken up but was blocking on getting the lock.
In the comparable situation with intrinsic locks it is spelled out in the apidoc that notify is delayed until the notifying thread releases its lock. The waiting thread can't act until then anyway. If that same situation occurs here that would not be surprising.
There isn't a contradiction in the javadoc in any case, waking up and acquiring the lock are two different things.