pthread-win32 扩展 sem_post_multiple

Posted

技术标签:

【中文标题】pthread-win32 扩展 sem_post_multiple【英文标题】:pthread-win32 extension sem_post_multiple 【发布时间】:2010-12-02 21:50:45 【问题描述】:

我目前正在围绕 pthread 构建一个精简的 C++ 包装器,以供内部使用。 Windows 和 QNX 都是目标,幸运的是 pthreads-win32 端口似乎工作得很好,而 QNX 符合 POSIX 以用于我们的实际目的。

现在,在实现信号量时,我点击了函数

sem_post_multiple(sem_t*, int)

这显然只在 pthreads-win32 上可用,但在 QNX 中没有。顾名思义,该函数应该通过作为第二个参数给出的计数来增加信号量。据我所知,该函数既不属于 POSIX 1b 也不属于 POSIX 1c。

虽然目前对上述功能没有要求,但我仍然想知道为什么 pthreads-win32 提供该功能以及它是否有用。我可以尝试使用类似于以下内容为 QNX 模仿它:

sem_post_multiple_qnx(sem_t* sem, int count)

   for(;count > 0; --count)
   
       sem_post(sem);
   
 

我要的是关于如何进行的建议/建议。如果共识建议为 QNX 实现该功能,我也会感谢 cmets 关于建议的代码剪切是否是可行的解决方案。

提前致谢。

PS:为了清楚起见,我故意省略了我喜欢的 C++ 类。对于所有建议加强救援的人:由于管理原因,这在我当前的项目中不是一个选项。

【问题讨论】:

当“管理层”参与技术决策时会发生这种情况... :) 如果您不需要它,为什么还要浪费时间来包装它?对我来说决定很明确,跳过它...... 确实,除非您确定需要它们,否则我会完全跳过包装 POSIX 信号量。信号量是 1990 年代(甚至更早?)的同步习语。 POSIX 互斥锁、条件变量、rwlock 和自旋锁在实践中更有用。 【参考方案1】:

在任何情况下,信号量都是 POSIX 中的可选扩展。例如 OS X 似乎没有完全实现它们。因此,如果您关心可移植性,无论如何您都必须提供所需功能的包装器。

您通过迭代sem_post 模拟原子增量的方法肯定有缺点。

它可能表现不佳, 通常sem_t 用于 性能关键环境。 此操作不会 原子。所以令人困惑的事情可能 在您完成循环之前发生。

我会坚持必要的、严格符合 POSIX 的要求。请注意,sem_timedwait 是信号量选项的另一个可选部分。

【讨论】:

+1 提到 sem_timedwait() 我也错过了一个扩展,因为它是在 QNX 中提供的【参考方案2】:

您提议的sem_post_multiple 实现与sem_getvalue 不能很好地配合,因为sem_post_multiple 是一个原子增加,因此对sem_getvalue 的“同时”调用不可能返回任何中间值.

就我个人而言,我希望将它们都排除在外:尝试将基本同步操作添加到缺少它们的系统中是无稽之谈,而且您的包装器可能很快就会不再“瘦”。所以除非你有使用sem_post_multiple的代码,否则不要进入它,你绝对必须移植。

【讨论】:

【参考方案3】:

sem_post_multiple() 是由 win32-pthreads 维护者引入的非标准辅助函数。您的实现与他们的不同,因为多次递减不是原子的。这是否是一个问题取决于预期用途。 (就个人而言,除非/直到需要,否则我不会尝试实现此功能。)

【讨论】:

与此同时,我瞥见了它们的实现,确实它们的代码与天真的循环完全不同。【参考方案4】:

这是一个有趣的问题。 +1。

我同意这里当前的普遍共识,即实现该功能可能不是一个好主意。尽管您提出的实现在大多数情况下可能都可以正常工作,但肯定存在由于非原子性而导致结果可能大不相同的情况。以下是一种(非常)人为的情况:

启动线程 A 调用 sem_post_multiple(s, 10) 等待 s 的线程 B 被释放。线程 B 杀死线程 A。

在上述不友好的情况下,原子版本将信号量增加 10。对于非原子版本,它可能只增加一次。这个例子在现实世界中肯定是不可能的。例如,杀死一个线程几乎总是一个坏主意,更不用说它可能使信号量对象处于无效状态这一事实。 Win32 实现可能会在信号量上留下互斥锁 - see this for why。

【讨论】:

绝对没有办法杀死不想被杀死的线程。 sem_post 不是取消点,所以 sem_post_multiple 不会有任何取消点,除非你做了一些愚蠢的事情来实现它。当然,您始终可以在操作期间禁用取消。 绝对,当然我的意思是不调用未定义的行为。当然有涉及随机内存地址的UB方法...... :-) @R - 我同意。这也是我使用“非常”和“做作”这两个词的原因。

以上是关于pthread-win32 扩展 sem_post_multiple的主要内容,如果未能解决你的问题,请参考以下文章

如何在Windows下编写基于Posix标准的多线程程序

sem_post的介绍

sem_post 是不是唤醒了一个随机进程

Sem_post() 无法正常工作,这既不是增加信号量的值,也不是解除阻塞附加到该信号量的进程[重复]

sem_wait sem_post信号量操作进本函数

线程同步之信号量(sem_init,sem_post,sem_wait)