为什么无法在 Java 中使用 if 语句构建二进制信号量
Why it is not possible to build binary semaphore with if statement inside in Java
我有一个小问题让我有点困惑。
这是我的代码:
public synchronized void P() {
while(!_state) {
this.wait();
}
_state = false;
}
该方法负责取信号量。
为什么不能使用 if
语句而不是 while
循环来构建二进制信号量?
oracle 文档说:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is
done with the object.
所以只有一个线程应该在 P() 方法中 -> 所以只有一个线程应该被 wait() 方法阻塞。其余线程应该在 P() 方法级别上被阻塞。但是当我将 while()
替换为 if()
时,它无法正常工作
synchronized
方法等同于synchronized(this)
块。
只允许1个线程进入同步块。通过进入它,线程获得锁。当您 wait
在同步块内时,您释放锁(对象监视器)并停放当前线程。此时,允许另一个线程进入该块。当其他线程将在调用 wait
的同一对象上调用 notify
或 notifyAll
时,执行将继续。当给定的同步块的锁被释放时,通知线程将 "exit wait state"。
总而言之 - wait 并不像您预期的那样工作,它不会阻塞执行,只是让等待线程休眠,允许其他线程获取同步锁。
所以您无法实现您想要的目标,因为 wait
的工作方式与您预期的不同。你想在这里使用的是ReentrantLock
。 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html
Why it is not possible to build binary semaphore with if
statement instead of while
loop?
要获得更深入的答案,您应该阅读 Oracle 的 Guarded Blocks tutorial。
简短的回答是,当 wait()
调用 returns:
时,_state
可能是 false
有几个原因
多个消费者:使用 notifyAll()
唤醒睡眠者通常比 notify()
更安全,并且如果您编写的程序中有两个或多个线程可以调用 P()
函数,您可能只希望在其他线程调用 V()
函数时允许其中的 一个 继续。所以,如果他们都 "wake up",你只需要设置一个 _state=false;
,你会希望其他人回去睡觉。
同一个对象因不止一个原因收到 notifyAll()
次调用。这不是好的做法,但它确实发生了,尤其是在许多开发人员为代码做出贡献的项目中。在这种情况下,如果由于错误的原因通知了对象,您不希望 P()
调用 return。你想让它回去继续等待。
o.wait()
的文档说允许 return 即使对象 o
根本没有被通知。这被称为 "spurious wakeup." 它很少发生,并且只在某些操作系统中发生,但它们允许它,因为它可以更有效地实现 wait()
和 notify()
.
我有一个小问题让我有点困惑。
这是我的代码:
public synchronized void P() {
while(!_state) {
this.wait();
}
_state = false;
}
该方法负责取信号量。
为什么不能使用 if
语句而不是 while
循环来构建二进制信号量?
oracle 文档说:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
所以只有一个线程应该在 P() 方法中 -> 所以只有一个线程应该被 wait() 方法阻塞。其余线程应该在 P() 方法级别上被阻塞。但是当我将 while()
替换为 if()
时,它无法正常工作
synchronized
方法等同于synchronized(this)
块。
只允许1个线程进入同步块。通过进入它,线程获得锁。当您 wait
在同步块内时,您释放锁(对象监视器)并停放当前线程。此时,允许另一个线程进入该块。当其他线程将在调用 wait
的同一对象上调用 notify
或 notifyAll
时,执行将继续。当给定的同步块的锁被释放时,通知线程将 "exit wait state"。
总而言之 - wait 并不像您预期的那样工作,它不会阻塞执行,只是让等待线程休眠,允许其他线程获取同步锁。
所以您无法实现您想要的目标,因为 wait
的工作方式与您预期的不同。你想在这里使用的是ReentrantLock
。 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html
Why it is not possible to build binary semaphore with
if
statement instead ofwhile
loop?
要获得更深入的答案,您应该阅读 Oracle 的 Guarded Blocks tutorial。
简短的回答是,当 wait()
调用 returns:
_state
可能是 false
有几个原因
多个消费者:使用
notifyAll()
唤醒睡眠者通常比notify()
更安全,并且如果您编写的程序中有两个或多个线程可以调用P()
函数,您可能只希望在其他线程调用V()
函数时允许其中的 一个 继续。所以,如果他们都 "wake up",你只需要设置一个_state=false;
,你会希望其他人回去睡觉。同一个对象因不止一个原因收到
notifyAll()
次调用。这不是好的做法,但它确实发生了,尤其是在许多开发人员为代码做出贡献的项目中。在这种情况下,如果由于错误的原因通知了对象,您不希望P()
调用 return。你想让它回去继续等待。o.wait()
的文档说允许 return 即使对象o
根本没有被通知。这被称为 "spurious wakeup." 它很少发生,并且只在某些操作系统中发生,但它们允许它,因为它可以更有效地实现wait()
和notify()
.