【问题标题】:How deterministic are Java semaphores guaranteed to be?Java 信号量的确定性如何保证?
【发布时间】: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


【解决方案1】:

在 cmets 关于问题 Slaw 中指出了 the documentation 的其他内容:

当 fairness 设置为 true 时,信号量保证调用任何获取方法的线程被选择以获得许可,按照它们调用这些方法的顺序被处理(先进先出;先进先出)。请注意,FIFO 排序必然适用于这些方法中的特定内部执行点。 因此,一个线程可以在另一个线程之前调用acquire,但在另一个线程之后到达排序点,同样在从方法返回时。

这里的重点是acquire() 是一个可中断 函数,它有一个开始和一个结束。在其异常期间的某个时刻,调用线程在公平队列中确保了一个位置,但是当它与同时访问同一函数的另一个线程相关时仍然是不确定的。将此点称为 X 并考虑两个线程,其中一个持有信号量。在某个时候另一个线程调用:

   sem.acquire()

无法保证调度程序不会在到达 X 点之前将 acquire() 内的线程搁置一边。 如果所有者线程执行此操作(例如,这可能是某种同步检查点或屏障控制):

   sem.release()
   sem.acquire()

它可以简单地释放和获取信号量而不会被另一个线程获取,即使该线程已经进入acquire

在调用之间注入Thread.sleep()yield() 可能通常有效,但这不是保证。要创建具有该保证的检查点,您需要两个锁/信号量来进行交换:

  • 所有者线程持有semA
  • 客户端线程可以使用semB,然后等待semA
  • 所有者可以释放semA,然后等待semB,如果另一个线程真的在等待semA,通过持有semB,将阻塞并保证semA现在可以被客户端获取。李>
  • 客户端完成后,释放semB,然后释放semA
  • 当所有者从等待semB中释放时,它可以获取semA并释放semB

如果这些被正确封装,这个机制是坚如磐石的。

【讨论】:

    猜你喜欢
    • 2011-02-02
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    相关资源
    最近更新 更多