简体   繁体   中英

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? 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

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. 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. 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 . I suggest you use those features instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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