我有生产者消费者问题需要稍作修改才能解决 - 有许多并行生产者,但在一个并行线程中只有一个消费者。当生产者在缓冲区中没有位置时,它只是忽略元素(不等待消费者)。我写了一些C伪代码:
struct Element
{
ULONG content;
volatile LONG bNew;
}
ULONG max_count = 10;
Element buffer* = calloc(max_count, sizeof(Element));
volatile LONG producer_idx = 0;
LONG consumer_idx = 0;
EVENT NotEmpty;
BOOLEAN produce(ULONG content)
{
LONG idx = InterlockedIncrement(&consumer_idx) % max_count;
if(buffer[idx].bNew)
return FALSE;
buffer[idx].content = content;
buffer[idx].bNew = TRUE;
SetEvent(NotEmpty);
return TRUE;
}
void consume_thread()
{
while(TRUE)
{
Wait(NotEmpty);
while(buffer[consumer_idx].bNew)
{
ULONG content = buffer[consumer_idx].content;
InterlockedExchange(&buffer[consumer_idx].bNew, FALSE);
//Simple mechanism for preventing producer_idx overflow
LONG tmp = producer_idx;
InterlockedCompareExchange(&producer_idx, tmp%maxcount, tmp);
consumer_idx = (consumer_idx+1)%max_count;
doSth(content);
}
}
}
我不是100%确定此代码是正确的。你能看到可能出现的问题吗?或者也许这段代码可以用更好的方式编写?
答案 0 :(得分:0)
不要使用全局变量来实现您的目标,尤其是在多线程应用程序中!请改用Semaphore而不是Lock,而是使用TryLock。如果TryLock失败,则意味着没有其他元素的空间,所以你可以跳过它。
在这里,您可以在WinAPI中找到有关信号量的内容,因为您可能会使用它:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686946(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx
您可以通过将0作为超时传递给WaitForSingleObject函数来实现TryLock功能。
答案 1 :(得分:0)
请阅读:http://en.wikipedia.org/wiki/Memory_barrier
C和C ++标准不涉及多个线程(或多个线程) 处理器),因此,volatile的用处取决于 编译器和硬件。虽然挥发性保证了挥发性 读取和易失性写入将按照指定的确切顺序发生 源代码,编译器可能生成代码(或CPU可能 重新排序执行)以便重新排序易失性读或写 关于非易失性读或写,从而限制其 作为线程间标志或互斥的有用性。而且,事实并非如此 保证可以看到易失性读写 由于缓存,缓存一致性协议和其他处理器的顺序 放松的记忆排序,意味着单独的易变变量可能不均匀 作为线程间标志或互斥体工作。
所以在一般情况下,只有volatile不适用于C. 但它可以用于某些特定的编译器/硬件和其他语言(例如Java 5)。