【问题标题】:pthread_mutex_init vs sem_init (Unshared)pthread_mutex_init vs sem_init(非共享)
【发布时间】:2012-07-24 10:20:01
【问题描述】:

我正在考虑更改一些我想在 linux、unix 和 OSX 上运行的代码。代码中有一些对 sem_init 的调用,但 pshared 值设置为零。我在 Rochkind 关于 unix 编程的书上做了一些阅读,他基本上说不共享的 sem_init 与 pthread_mutex_init 相同,因为它以内存中的二进制方式运行。

问题是 - 我可以安全地将这些 sem_init 更改为 pthread_mutex_init,还是使用 sem_open 来获得此代码的更便携版本?

OSX 不支持未命名的信号量,但我猜其他两个支持。我真的不想有一个单独的编译标志 #ifdef(__APPLE__) 或其他东西。

谢谢

【问题讨论】:

  • 如果我关心支持这样一个损坏的操作系统,我会为 OSX 正确实现 sem_* 接口的 libosxsemaphore 库,然后要求安装它并链接我的应用程序在 OSX 上构建时反对它。可能破坏您的代码以解决 OSX 被破坏的问题似乎不是一个好主意...

标签: c macos unix pthreads semaphore


【解决方案1】:

互斥量和信号量具有不同的语义。互斥锁必须由获得锁的同一线程解锁。所以锁定/解锁必须总是成对出现在同一个线程中。

信号量更加灵活,因为另一个线程可以发布另一个线程使用的令牌。例如,它们通常用于实现生产者/消费者模式。因此,您必须检查要移植的程序是否符合互斥锁的受限语义。

【讨论】:

  • +1 这个答案抓住了关键的区别以及你不能用另一个替换一个的原因。
  • 这是一件好事。我相信这段代码是在 FreeBSD 中开发的,看起来这个信号量和 pthread 的组合正在被使用。信号量的发布和等待是从同一进程中的两个不同线程调用的。由于 pshared 标志设置为零,我不会想到这会与该模型一起使用。
  • 那你真的要小心了。也许背后的逻辑也可以与互斥锁相匹配,但这实际上是一种语义转换,而不仅仅是句法转换。如果不可能,您应该研究pthread_mutex_tpthread_cond_t 的组合以获得相同的效果。
【解决方案2】:

互斥量和信号量的语义不同。确实,如果非共享信号量仅用作二进制信号量,即它的值永远不会大于 1,则它等同于互斥锁。但是,这是您需要从代码的逻辑中确定的东西,而不是它如何确定被初始化。如果您确定信号量仅用作二进制信号量,那么 pthread 互斥锁是完美的替代品。如果没有,您可以使用 sem_open() 来实现可移植性,或者编写一个包装器,使用 pthread 互斥锁和条件变量来模拟信号量。

【讨论】:

    【解决方案3】:

    在给定的实例中切换到互斥锁应该是安全的。如果一次只有一个线程可以进入给定的临界区,那么无论是否编写为信号量,您都有效地拥有了一个互斥锁。但是,根据操作系统实现功能的方式,您可能会获得不同的性能特征。这不是我会失眠的事情,但仍然是测试时要记住的事情。

    【讨论】:

    • sem_open 呢?我在想,如果我切换到 sem_open,我就不必修改已在互斥锁上具有 sem_wait 的其余代码。听起来合理吗?我不太确定我需要什么参数,我将权限设置为 0644,并在旧代码中保留了与 sem_init 相同的值(当然是 O_CREAT)
    • 它返回一个 sem_t,所以是的,它可以与您的其他信号量函数一起正常工作。至于参数,老实说我以前没用过。查看 linux.die.net 上的 API,您的论点听起来像是可行的。我个人会以在信号量上完成任务所需的最低权限进行,但所有这些内容都将特定于您的程序需求。
    猜你喜欢
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多