首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >可升级互斥锁位于Windows和Linux上的共享内存中

可升级互斥锁位于Windows和Linux上的共享内存中
EN

Stack Overflow用户
提问于 2016-02-15 08:31:30
回答 2查看 643关注 0票数 0

我有两个名为Writer和Reader的进程在同一台机器上运行。编写器是一个单数线程,它将数据写入共享内存。读取器有8个线程,它们打算同时从共享内存读取数据。我需要一个符合以下条件的锁定机制:

1)一次允许作家或阅读器访问共享内存。

2)如果Reader拥有从共享内存读取数据的权限,那么它的所有线程都可以读取数据。

3) Writer必须等到Reader“完全”释放锁(因为它有多个线程)。

我读过很多关于可共享互斥的文章,这似乎是解决问题的方法。在这里,我更详细地描述了我的系统:

1)系统应同时在Windows和Linux上运行。

2)将共享内存划分为两个区域:锁和数据。数据区域进一步划分为100个块。我打算创建100个“锁对象”(可共享互斥对象),并将它们放置在锁区域。这些锁对象用于100个数据块的同步,1个锁对象用于1个数据块。

3)作者,读者首先决定要访问哪个块,然后尝试获取适当的锁。一旦获得锁,它就在数据块上执行。

我现在关注的是:

在Windows和Linux (Centos)上是否有“内置”方法将锁对象放置在共享内存上,然后不用boost库就可以对对象进行锁定/解锁。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-24 21:35:51

编辑:2016年2月25日,格林尼治时间09:30

我可以提出一些建议。这确实取决于需求。

  1. 如果看来这个可升级的助推互斥装置符合要求的话,那就用它吧。从5分钟开始阅读似乎可以在shm中使用。我没有经验,因为我不使用助推。Boost在Windows和Linux上是可用的,所以我看不出为什么不使用它。您可以始终抓取您喜欢的特定代码,并将其放入您的项目中,而不需要拖拽整个庞然大物。 不管怎么说,这不是很容易测试和看到它足够好吗?
  2. 我不明白在shm中放置锁的要求。如果这不是真正的需求,并且您希望使用OS本机对象,那么每个OS都可以使用不同的机制。比如说,在Windows上命名互斥锁(不是在shm中),在Linux上命名pthread_rwlock。
  3. 我知道我更喜欢用什么: seqlock。 我在低延迟领域工作,所以我选择的是尽可能低的延迟。我用cpu周期来测量它。 从您提到的每个对象都需要一个锁,而不是一个大锁,我认为性能是很重要的。 不过,这里有一些重要的问题:
代码语言:javascript
复制
- Since it's in shm, I assume it's POD (flat data)? If not, you can switch to a read/write spinlock. 
- Are you ok with spinning (busy wait) or do you want to sleep-wait? seqlocks and spinlocks are no OS mechanism, so there's nobody to put your waiting threads to sleep. If you do want to sleep-wait, read #4
代码语言:javascript
复制
- If you care to know the other side (reader/write) died, you have to impl that in some other way. Again, because seqlock is no OS beast. If you want to be notified of other side's death as part of the synchronization mechanism, you'll have to settle for named mutexes, on Windows, and on robust mutexes, in shm, on Linux

自旋锁和seqlock提供了最大的吞吐量和最小的延迟。在内核支持的同步中,很大一部分延迟用于用户和内核空间之间的切换。在大多数应用程序中,这不是一个问题,因为同步只在一小部分时间内发生,几微秒的额外延迟是可以忽略不计的。即使在游戏中,100 fps每帧给你留下10毫秒,这是永恒的互斥锁/解锁。

  1. 自旋锁的替代物通常并不贵得多。 在Windows中,关键部分实际上是一个自旋锁,它具有使用事件对象的备份机制.这是使用shm和命名事件重新实现的,名为https://msdn.microsoft.com/en-us/library/ms810428.aspx。 在Linux中,线程互斥对象是基于futex的。futex就像Windows上的事件。无争用的非鲁棒互斥体只是自旋锁. 当另一方死亡时,这些家伙仍然不给你通知。

加注2016年2月26日格林尼治时间10:00

如何添加您自己的所有者死亡检测:

名为互斥锁和线程健壮互斥的Windows具有内置的能力。在使用其他锁类型时,很容易自己添加它,并且在使用基于用户空间的锁时也是非常必要的。

首先,我不得不说,在许多情况下,简单地重新启动所有东西而不是检测所有者的死亡更合适。它肯定更简单,因为您还必须从不是原始所有者的进程中释放锁。

无论如何,本机检测进程死亡的方法在Windows上很容易--进程是可等待的对象,所以您只需等待它们。您可以等待零时间立即检查。

在Linux上,只有家长才会知道孩子的死,这样就不那么琐碎了。父级可以获得SIGCHILD,也可以使用waitpid()

我最喜欢的检测过程死亡的方法是不同的。我连接两个进程之间的一个非阻塞TCP套接字,并信任操作系统在进程死亡时杀死它。

当您尝试从套接字(任何一边)读取数据时,如果对等方已经死了,您将读取0字节。如果它还活着,你会得到EWOULDBLOCK

显然,这也适用于盒子之间,所以让它一劳永逸地做起来很方便。

您的员工循环将不得不更改以交错同行死亡检查,这是通常的工作。

票数 1
EN

Stack Overflow用户

发布于 2016-02-15 08:38:16

代码语言:javascript
复制
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>**    

//Mutex to protect access to the queue
    boost::interprocess::interprocess_mutex      mutex;

   //Condition to wait when the queue is empty
    boost::interprocess::interprocess_condition  cond_empty;

    //Condition to wait when the queue is full
    boost::interprocess::interprocess_condition  cond_full;
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35404615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档