【发布时间】:2017-04-07 00:39:32
【问题描述】:
我想实现一个具有单个生产者和单个消费者的缓冲区,其中只有消费者可能被阻止。这里的重要细节是,如果队列已满,生产者可以删除更新。
我考虑过转换一个无等待的实现,但乍一看似乎没有简单的方法可以在不丢失通知的情况下通知消费者新数据已到达。所以我选择了下面非常简单的方法,使用计数信号量(为清楚起见,省略了一些错误处理细节):
Object ar[SIZE];
int head = 0, tail = 0;
sem_t semItems; // initialized to 0
void enqueue(Object o) {
int val;
sem_getvalue(&semItems, &val);
if (val < SIZE - 1) {
ar[head] = o;
head = (head + 1) % SIZE;
sem_post(&semItems);
}
else {
// dropped
}
}
Object dequeue(void) {
sem_wait(&semItems);
Object o = ar[tail];
tail = (tail + 1) % SIZE;
return o;
}
此代码是否存在任何安全问题?我很惊讶在流行文献中没有看到类似的实现。另一个问题是sem_post() 是否会阻塞(在 linux 的后台调用futex_wake())。当然也欢迎更简单的解决方案。
编辑:编辑代码以在读者和作者之间留出空间(参见 Mayurk 的回复)。
【问题讨论】:
-
我能知道你为什么只需要阻止消费者吗?
-
@SumitGemini 当流量很大时,消费者应该比生产者运行得慢,因为生产者与硬件对话。这只是我正在研究的一种可能方法,可能是隐式 CAS 循环实际上使情况变得更糟。
-
@SumitGemini 刚刚发现了一个关于原生 C++ 信号量的提案,它可以更好地解释它:open-std.org/jtc1/sc22/wg21/docs/papers/2006/…
标签: c multithreading pthreads semaphore