我的数组包含4096个元素。考虑到“写者优先读者-写者”问题的解决方案,该问题在“Little Book of Semaphores”(第85页)中提出,我的应用程序需要每个数组元素5个信号量。这总共需要约20000个信号量(或等效地,20000个互斥量+20000个条件变量)。
我的应用程序的另一个特点是,在给定时间内,大多数信号量都不活动(通常有约32个“客户端”线程在等待/信号上千个信号量)。请注意,由于整个服务器在单个进程中运行,我使用轻量级、基于线程的信号量(而不是进程间信号量)。
我的问题有两个方面:
- 在Linux和Windows系统下,对于一个单一进程创建20000个信号量是不推荐的。但实际上,似乎也不需要这么多。
- 如果不建议这种做法,可以使用哪些技术来减少实际信号量的数量呢?例如,在一个实际信号量的基础上创建一组N个“模拟信号量”。这可能是一个有趣的解决方案,因为在给定时间大部分信号量都是不活跃的。
- 使用成千上万个信号量不建议,特别是从跨平台的角度考虑。因此,即使它们不是进程间信号量(在Windows下仍然会消耗句柄)。
- 解决我的问题的直接方法是将我的数组分成例如16个元素的64个子数组,并将每个子数组与一个读/写锁相关联。不幸的是,这会引入很多争用(1个写者将阻塞对15个元素的读取)。
深入研究Boost源代码,我发现:
- "boost::mutex"的实现在Windows下不包装CRITICAL_SECTION对象(而是CreateEvent和ReadWriteBarrier),
- "boost::shared_mutex"在Windows下使用CreateSemaphore(它们是沉重的进程间对象),并且
- "boost::shared_mutex"在Linux下不包装"pthread_rwlock_t"。
这样做的原因对我来说似乎不太清楚。特别是,在Windows下使用进程间对象作为"boost::shared_mutex"的子优化。
到目前为止的问题总结
- 如何在一个实际的信号量上创建一组N个“模拟信号量”,使得模拟信号量之间的争用尽可能小?
- boost::mutex和boost::shared_mutex与它们的本机对应物(CRITICAL_SECTION和pthread_rwlock_t)相比如何?