gpt4 book ai didi

c++ - 具有两个线程的 STL 队列(生产者、消费者)

转载 作者:太空狗 更新时间:2023-10-29 21:25:05 27 4
gpt4 key购买 nike

我想要队列安全的临界区,这样线程就不会同时访问队列。即使我注释了与关键部分相关的行,此代码也能正常工作。谁能解释一下为什么?

queue<int> que;
CRITICAL_SECTION csection;
int i=0;

DWORD WINAPI ProducerThread(void*)
{

while(1)
{
//if(TryEnterCriticalSection(&csection))
{
cout<<"Pushing value "<<i<<endl;
que.push(i++);
//LeaveCriticalSection(&csection);
}
}
}

//Consumer tHread that pops out the elements from front of queue
DWORD WINAPI ConsumerThread(void*)
{
while(1)
{
//if(TryEnterCriticalSection(&csection))
{
if(!que.empty())
{
cout<<"Value in queue is "<<que.front()<<endl;
que.pop();
}
else
Sleep(2000);
//LeaveCriticalSection(&csection);
}
}
}

int _tmain(int argc, _TCHAR* argv[])
{
HANDLE handle[2];
//InitializeCriticalSection(&csection);
handle[0]=NULL;
handle[1]=NULL;
handle[0]=CreateThread(0,0,(LPTHREAD_START_ROUTINE)ProducerThread,0,0,0);
if(handle[0]==NULL)
ExitProcess(1);

handle[1]=CreateThread(0,0,(LPTHREAD_START_ROUTINE)ConsumerThread,0,0,0);
if(handle[1]==NULL)
ExitProcess(1);

WaitForMultipleObjects(2,handle,true,INFINITE);

return 0;
}

最佳答案

意外地有效,大概有两个原因:

  1. 它不起作用,但你永远不会注意到。消费者拉取队列中的任何内容,或者它认为队列中的任何内容。如果什么都没有,它会一直睡到生产者推送了一些东西。这“有效”是因为生产者只追加到末尾,而消费者只从头开始读取。除了更新 size。您很可能最终会有一个队列,该队列处于存在元素但 size 未反射(reflect)它的状态。这很糟糕,但相反的情况更糟糕,而且迟早会发生。
    你无法知道。好吧,您最终可能会知道,如果排队的工作项由于某种原因“消失”了,或者如果您用完了内存,那么请尝试找出原因。
  2. 您使用 printf(或 std::cout,两者相同),它在内部被临界区锁定。这种“某种”方式以您需要的方式锁定对队列的访问,除非不需要。它将在 99.9% 的时间内工作(偶然的,因为消费者将被阻止尝试打印,这比生产者添加到队列中需要更长的时间来唤醒)。但是,当打印后上下文切换发生时,它突然失败。砰,你死定了。

您确实绝对需要使用临界区对象或互斥体来保护临界代码区。否则,结果不可预测。与人们可能相信的相反,“但它有效”并不是一件好事,这是可能发生的最糟糕的事情。因为它只会在它不起作用之前起作用,然后你就不知道为什么了。

也就是说,您可以使用 IO 完成端口,它可以非常高效地为您完成所有工作。您可以使用 GetQueuedCompletionStatus从端口中提取“事件”并使用 PostQueuedCompletionStatus发布一个。完成端口完成队列的整个处理,包括为您正确同步到多个消费者(并且它以 LIFO 顺序执行,这有利于避免上下文切换和缓存失效)。
每个事件都包含一个指向 OVERLAPPED 结构的指针,但完成端口不使用它,您可以传递 any 指针(或者,如果您觉得那样更好,传递指向 OVERLAPPED 的指针,后跟您自己的数据)。

关于c++ - 具有两个线程的 STL 队列(生产者、消费者),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14562922/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com