成千上万的读/写器锁在一个进程中

Tis*_*sys 6 c c++ synchronization semaphore cross-platform

我目前正在设计一个具有大规模同步模式的C++跨平台(Linux/Windows)服务器应用程序.我在内部使用boost :: thread作为特定于操作系统的线程的抽象.我的问题是保护数据数组,数组的每个元素都受独立的读/写锁保护.

我的数组包含4096个元素.考虑到" 信号量小书 "(第85页)中提出的"作者优先级读者 - 作者"问题的解决方案,我的应用程序每个数组元素需要5个信号量.这总共提供了大约20000个信号量(或者,相当于20000个互斥量+ 20000个条件变量).

我的应用程序的另一个特点是在给定时间内,大多数信号量都不活动(通常有大约32个"客户端"线程在数千个信号量上等待/发送信号).请注意,由于整个服务器在单个进程中运行,因此我使用轻量级,基于线程的信号量(不是进程间信号量).

我的问题是双重的:

  1. 是否建议在Linux和Windows上为单个进程创建总计20000个信号量?嗯,当然,我想情况并非如此......

  2. 如果不推荐这种做法,我可以使用什么技术来减少实际信号量的数量,例如在1个实际信号量的顶部创建一组N个"模拟信号量"?我想这将是一个有趣的解决方案,因为我的大多数信号量在给定时间都处于非活动状态.

提前致谢!

到目前为止答案的摘要

  1. 建议不要使用数千个信号量,尤其是从跨平台的角度来看.所以,即使它们不是进程间信号量(它们仍然在Windows下使用句柄).
  2. 解决我的问题的直接方法是将我的数组拆分为例如64个16个元素的子数组,并将这些子数组中的每一个与一个读/写锁相关联.不幸的是,这引入了很多争用(1个写入器会阻止读取到15个元素).
  3. 深入研究Boost源代码,我发现:

    • "boost :: mutex"的实现不包装Windows下的CRITICAL_SECTION对象(但是CreateEvent和ReadWriteBarrier),
    • "boost :: shared_mutex"在Windows下使用CreateSemaphore(重量级,进程间对象),以及
    • "boost :: shared_mutex"不会在Linux下包装"pthread_rwlock_t".

    其中的原因似乎并不清楚.特别是,在Windows下使用"boost :: shared_mutex"的进程间对象对我来说似乎不是最优的.

迄今为止的公开问题摘要

  1. 如何在1个实际信号量的顶部创建一组N个"模拟信号量",使模拟信号量之间的争用尽可能小?
  2. "boost :: mutex"和"boost :: shared_mutex"与其原生对应物(CRITICAL_SECTION和pthread_rwlock_t)相比如何?

小智 1

  1. 不建议这样做。实际上您不应该这样做,因为在 Windows 中,每个信号量会消耗 1 个句柄对象。一个进程只能管理特定数量的 Handles 对象。线程/进程和其他Windows对象可能需要使用Handle对象,如果不能使用就会崩溃。这与 Linux 中的文件描述符概念类似。

  2. 将 4096 个元素分成 30 个(例如)组,每组 140 个元素,并为每个 140 组分配一个信号量。然后 30 个(在本示例中)线程将尝试访问这 30 个集合,并且它们将基于每个 140 组信号量进行同步化。