简体   繁体   English

使用 pthreads 创建线程安全队列是否正确?

[英]is it correct way to create a thread safe queue using pthreads?

I recently started learning multithreading, so I still don't understand some things.最近开始学习多线程,所以有些东西还是不太明白。 I tried to write a thread-safe queue, but I doubt if I did everything right.我试图写一个线程安全的队列,但我怀疑我是否做对了。 Since I do not quite notice my mistakes, I would be glad if you pointed them out to me.由于我没有注意到我的错误,如果您向我指出错误,我会很高兴。 Thank you for your responses, Also.谢谢你的回复,还有。 I'm not sure if I am using a conditional variable correctly in this code.我不确定我是否在此代码中正确使用了条件变量。

template<class T>
class SafeQueue {
private:
    std:: queue<T> _data;
    pthread_mutex_t _mutex;
    pthread_cond_t _condition;
public:
    SafeQueue();
    ~SafeQueue();
    void push(const T &x);
    T front();
    T back();
    void pop();
    int size();
    bool empty();
};

template<class T>
SafeQueue<T>::SafeQueue(){
    pthread_mutex_init(&_mutex, NULL);
    pthread_cond_init(&_condition, NULL);
}

template<class T>
SafeQueue<T>::~SafeQueue(){
    pthread_mutex_destroy(&_mutex);
    pthread_cond_destroy(&_condition);
}

template<class T>
void SafeQueue<T>::push(const T &x){
    pthread_mutex_lock(&_mutex);
    _data.push(x);
    pthread_cond_signal(&_condition);
    pthread_mutex_unlock(&_mutex);
}

template<class T>
T SafeQueue<T>::front(){
    pthread_mutex_lock(&_mutex);
    if(_data.empty() && _data.size() == 0){
        pthread_mutex_unlock(&_mutex);
        throw SafeQueueException("Queue is empty");
    }
    if(_data.empty()){
        pthread_cond_wait(&_condition, &_mutex);
    }
    T temp = _data.front();
    pthread_mutex_unlock(&_mutex);
    return temp;
}

template<class T>
T SafeQueue<T>::back(){
    pthread_mutex_lock(&_mutex);
    if(_data.empty() && _data.size() == 0){
        pthread_mutex_unlock(&_mutex);
        throw SafeQueueException("Queue is empty");
    }
    if(_data.empty()){
        pthread_cond_wait(&_condition, &_mutex);
    }
    T temp = _data.back();
    pthread_mutex_unlock(&_mutex);
    return temp;
}

template<class T>
void SafeQueue<T>::pop(){
    pthread_mutex_lock(&_mutex);
    if(_data.empty() && _data.size() == 0){
        pthread_mutex_unlock(&_mutex);
        throw SafeQueueException("Queue is empty");
    }
    if(_data.empty()){
        pthread_cond_wait(&_condition, &_mutex);
    }
    _data.pop();
    pthread_mutex_unlock(&_mutex);
}

template<class T>
int SafeQueue<T>::size(){
    pthread_mutex_lock(&_mutex);
    int temp = _data.size();
    pthread_mutex_unlock(&_mutex);
    return temp;
}

template<class T>
bool SafeQueue<T>::empty(){
    pthread_mutex_lock(&_mutex);
    bool temp = _data.empty();
    pthread_mutex_unlock(&_mutex);
    return temp;
}

some points in code i did not understand very well why you put _data.empty() && _data.size() == 0 something like this?代码中的一些点我不太明白为什么你把_data.empty() && _data.size() == 0这样的东西? when you can use only one of them.当您只能使用其中一个时。 and also there is no need lock for size and empty method because they are only reading variable and returned them they do not modify anything.而且也不需要锁定大小和空方法,因为它们只是读取变量并返回它们,它们不会修改任何东西。

BTW.顺便提一句。

it is true that some people think if they put mutex in start and end operation is some data structure(in your case queue) then they think it's thread safe now but it's NOT TRUE.确实有些人认为如果他们将互斥锁放在开始和结束操作中是一些数据结构(在你的情况下是队列),那么他们认为它现在是线程安全的,但它不是真的。

for example imagine your queue has one element.例如,假设您的队列有一个元素。

q = 1 q = 1

then after that you have some code like this:然后你有一些这样的代码:

if (!q.empty()) {
  auto element = q.back();
  q.pop();
}

in this example two thread going to execute this piece of code check and they will notice queue is not empty after that they will go inside if condition and one of threads first get back element then after that with luck same thread will pop element.在这个例子中,两个线程将执行这段代码检查,他们会注意到队列不为空,然后他们将在内部 go 条件和一个线程首先取回元素,然后运气好,同一个线程将弹出元素。 after that thread two going to get back element both since thread 1 popped element and now queue is empty then thread 2 back method fail with exception so thread 2 was entered in if condition with condition of queue is not empty then it failed.在那之后,线程 2 将取回元素,因为线程 1 弹出元素并且现在队列为空,然后线程 2 返回方法失败并出现异常,因此如果队列条件不为空,则进入线程 2 则失败。 so this queue is not thread safe所以这个队列不是线程安全的

Nice to see you are expanding your skills.很高兴看到你正在扩展你的技能。 If you are using C++ then C++11 onwards has threading in the standard library .如果您使用的是 C++,那么 C++11 之后的标准库中有线程。 I suggest you use those features instead.我建议您改用这些功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM