【发布时间】:2020-06-21 19:17:37
【问题描述】:
Semaphore.release() 的 (Oracle) javadoc 包括:
如果有任何线程试图获取许可,则选择一个并给予刚刚释放的许可。
这是一个艰难的承诺吗?这意味着如果线程 A 在 acquire() 中等待并且线程 B 这样做:
sem.release()
sem.acquire()
那么release() 应该将控制权传递给 A,而 B 将在 acquire() 中被阻止。如果只有这两个线程可以持有信号量并且 doc 语句在形式上为真,那么这是一个完全确定的过程:之后,A 将获得许可,B 将被阻塞。
但这不是真的,或者至少在我看来是这样的。我没有在这里为 SSCCE 烦恼,因为我真的只是在寻找确认:
竞争条件适用: 即使线程 A 正在等待许可,但当它被释放时,它可以立即被线程 B 重新获取,而线程 A 仍然被阻塞。 em>
如果这有什么不同的话,这些是“公平”的信号量,我实际上是在 kotlin 中工作的。
【问题讨论】:
-
"这个类的构造函数可选地接受一个公平参数。当设置为false时,这个类不保证线程获得许可的顺序。特别是允许插入,即, 调用acquire() 的线程可以在一直等待的线程之前分配一个许可-逻辑上新线程将自己置于等待线程队列的头部。当公平设置为true时,信号量保证调用任何线程的线程选择获取方法中的一些以按照它们调用这些方法的顺序获得许可..."
-
"...已处理(先进先出;FIFO)。请注意,FIFO 排序必然适用于这些方法中的特定内部执行点。因此,有可能一个线程在另一个线程之前调用acquire,但在另一个线程之后到达排序点,并且从该方法返回时类似。还请注意,不定时的tryAcquire方法不遵守公平设置,但会接受任何可用的许可。" –
SemaphoreJavadoc。 -
附注 - Windows 原生信号量、互斥体、... 是 FIFO,按请求的顺序提供服务。 “不公平”情况的问题在于,释放信号量不会强制上下文切换,因此当前运行的线程或进程继续运行并且可以立即重新获取(时间片上下文的罕见情况除外开关在发布后发生)。对于一组基于信号量的队列,其中每个信号量不需要多个服务器,那么一种解决方法是每个线程或进程使用一个信号量。
-
前三个cmet回答了你的问题还是还有什么不清楚的地方?
-
@akuzminykh 是的,他们回答了这个问题——如果其他人不回答,我会将其放入后代等的答案中。谢谢大家,一如既往。
标签: java multithreading kotlin semaphore race-condition