gpt4 book ai didi

c++ - 推送和弹出的不同互斥量

转载 作者:行者123 更新时间:2023-11-30 00:58:48 26 4
gpt4 key购买 nike

我有一个名为“subscribedQueue”的类。此类通过其订阅的发布者(复数)调用其 push 方法接收其数据。

在另一个线程中,调用此类的 pop 方法来接收该数据。因此,在某种意义上,此类是多个发布者及其订阅者之间的一种缓冲区。对于实现,我自己基于找到的有关线程安全队列的信息 here .

现在我的问题是双重的:

  • 如果我使用相同的互斥锁来推送和弹出值(目前我使用两个不同的互斥锁),我的程序是否有可能卡住,等待阻塞的推送?
  • 如果不是,push 和 pop 方法怎么可能通过'lock(the_same_mutex)'。

我的假设是,如果我使用相同的互斥量并且程序进入 pop 方法,它将在 pop 中获取锁,检查队列是否为空并等待永远不能在 pop 中设置的条件变量push 方法(因为锁已经被 pop 获取)。

当前代码(使用两个不同的互斥体):

#include <boost/thread.hpp>
#include <queue>
#include "subscriber.h"
#include "pubdata.h"
#ifdef DEBUG
#include <iostream>
#include <boost/lexical_cast.hpp>
#endif

namespace PUBLISHSUBSCRIBE
{
template<class T>
class SubscribedQueue: public PUBLISHSUBSCRIBE::Subscriber<T>, private std::queue< PubData<T> >
{
public:
PubData<T> pop(); //removes the next item from the queue, blocks until the queue is not empty
void push(const PubData<T> data); //method used by the publisher to push data onto the queue
private:
mutable boost::mutex writeMutex_; //only needed for publishing/pushing data
mutable boost::mutex readMutex_; //only needed for reading/popping data
boost::condition_variable notify_;
};

template<class T>
PubData<T> SubscribedQueue<T>::pop() { //Blocks until the queue is not empty
boost::mutex::scoped_lock lock(readMutex_);
while(std::queue< PubData<T> >::empty())
notify_.wait(lock); //block until recieving a notification AND the queue is not empty
PubData<T> head = std::queue< PubData<T> >::front();
std::queue< PubData<T> >::pop();
#ifdef DEBUG
std::string debugOut("pop: " + boost::lexical_cast<std::string>(head) + " - timestamp: " + boost::lexical_cast<std::string>(head.timestamp()) + " - from: " + boost::lexical_cast<std::string>(this) + "\n" );
std::cout <<debugOut;
#endif
lock.unlock();
return head;
}

template<class T>
void SubscribedQueue<T>::push(const PubData<T> data){
boost::mutex::scoped_lock lock(writeMutex_);
#ifdef DEBUG
std::cout << "published: " << data << std::endl;
#endif
std::queue< PubData<T> >::push(data);
lock.unlock();
notify_.notify_one();
}
}
#endif //SUBSCRIBEDQUEUE_H

[edit] 最让我担心的是:我有一个 boost::condition_variable notify_,它在 pop 中执行“等待通知”。但是 pop 必须首先锁定互斥锁,同一个互斥锁也必须锁定在“push”中才能“通知”条件变量。

所以这不会导致死锁,为什么不呢?

最佳答案

标准库容器不是线程安全的;如果您尝试同时从多个线程修改容器,那么<​​em>不好的事情就会发生。

如果您有一个用于推送和弹出操作的单独互斥锁,那么您无法防止来自两个线程的同时推送和弹出操作,因此您根本没有真正保护集合。

My assumption is that, if I would use the same mutex and the program enters the pop method, it will acquire the lock in pop, check if the queue is empty and wait on the condition variable which can never be set in the push method (as the lock is already acquired by pop).

当您在 pop 中等待条件变量时,wait() 解锁 互斥量,因此等待时的 push() 将能够锁定它。 push() 调用 notify_one() 并通过在函数末尾超出范围的 scoped_lock 解锁互斥体。然后,当下次调度 pop() 线程时,它会立即重新锁定互斥量并继续。

关于c++ - 推送和弹出的不同互斥量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5592583/

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