ThreadSafe Queue c ++ - PullRequest
       4

ThreadSafe Queue c ++

2 голосов
/ 14 января 2020

Я пытаюсь создать потокобезопасную очередь в c ++ с помощью std::mutex и std::condition_variable. Код

#include <iostream>
#include<thread>
#include<queue>
#include<atomic>
#include<mutex>
#include<condition_variable>

using namespace std;

template<class T>
class SafeQueue{
public:
    queue<T>qu;
    mutex mut;
    condition_variable cv;
    SafeQueue(){}
    SafeQueue(queue<T>q):qu(q){}
    void push(int val){
        unique_lock<mutex>uq(mut);
        cv.wait(uq,[&](){return qu.empty();});
        qu.push(val);
        uq.unlock();
    }
    bool isEmpty(){
//      unique_lock<mutex>uq(mut);
//      uq.unlock();
        cv.notify_all();
        return qu.empty();
    }
};
void inc(SafeQueue<int>& sq){
    for(int i=0;i<10;i++)
        continue;
    if(sq.isEmpty())
        sq.push(1);
}
void inc1(SafeQueue<int>& sq){
    for(int i=0;i<10;i++)
        continue;
    if(sq.isEmpty())
        sq.push(2);
}

int main(){
    queue<int>qu;
    SafeQueue<int> sq(qu);
    thread t1(inc,ref(sq));
    thread t2(inc1,ref(sq));
    t1.join();
    t2.join();
    cout<<sq.qu.front();
}

Потоковая безопасная очередь должна выводить 1 в конец, но вывод является случайным либо 1, либо 2, что означает, что он не является потокобезопасным. Почему эта конкретная программа не работает?

Ответы [ 2 ]

4 голосов
/ 14 января 2020

Это не означает, что программа не является поточно-ориентированной. Это не означает, что он некорректно определен и может создавать sh.

. Это просто означает, что логика вашей программы c не написана для добавления элементов в очередь в каком-либо определенном порядке.

Если вы хотите, чтобы эти два элемента были добавлены в определенном порядке c, pu sh из потока one .

Безопасность потока не означает, что ваше приложение работает как если бы он имел только один поток.

Ваша программа работает нормально.

0 голосов
/ 14 января 2020

Есть несколько аспектов, в которых ваш код имеет недостатки:

  • Каждый раз, когда вы получаете доступ к общей структуре, она должна быть защищена мьютексом. У вас есть мьютекс, но вы не используете его в isEmpty(). Документ, что связь, это важно, чтобы не потерять след. Также сделайте то же самое для CV, документа, когда он сигнализируется.
  • Относительно isEmpty(), эта функция в любом случае бесполезна. Даже если очередь не была пустой в один момент времени, ничто не мешает ей стать пустой в следующую секунду.
  • Перечитайте документацию для unique_lock. Ваш способ его использования сложнее, чем необходимо.
  • Использование CV также странно: как правило, вы используете его для уведомления официантов об изменениях. Вы безоговорочно сигнализируете об этом в функции, которая, кажется, только запрашивает некоторое состояние.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...