线程安全队列c++
ThreadSafe Queue c++
我正在尝试在 std::mutex
和 std::condition_variable
的帮助下在 C++ 中创建线程安全队列。代码
#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
这意味着它不是线程 safe.Why这个特定的程序不工作吗?
它并不意味着该程序不是线程安全的。这并不意味着它定义不明确并且会崩溃。
这只是意味着您的程序逻辑未编写为以任何特定顺序将项目添加到队列中。
如果您希望以特定顺序添加这两项,请从 一个 线程推送两者。
线程安全并不意味着您的应用程序就像只有一个线程一样运行。
您的程序运行良好。
您的代码存在几个方面的缺陷:
- 无论何时访问共享结构,都必须由互斥锁保护。你有一个互斥量,但你没有在
isEmpty()
中使用它。记录该连接,这很重要,不要迷失方向。此外,对 CV 执行相同的操作,在发出信号时进行记录。
- 关于
isEmpty()
,那个功能反正没用。即使队列在某个时间点不为空,也没有什么可以阻止它在下一秒变空。
- 重新阅读
unique_lock
的文档。你的使用方式比必要的更复杂。
- CV 的用途也很奇怪:通常,您用它来通知服务员变化。你在一个似乎只查询某些状态的函数中无条件地发出信号。
我正在尝试在 std::mutex
和 std::condition_variable
的帮助下在 C++ 中创建线程安全队列。代码
#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
这意味着它不是线程 safe.Why这个特定的程序不工作吗?
它并不意味着该程序不是线程安全的。这并不意味着它定义不明确并且会崩溃。
这只是意味着您的程序逻辑未编写为以任何特定顺序将项目添加到队列中。
如果您希望以特定顺序添加这两项,请从 一个 线程推送两者。
线程安全并不意味着您的应用程序就像只有一个线程一样运行。
您的程序运行良好。
您的代码存在几个方面的缺陷:
- 无论何时访问共享结构,都必须由互斥锁保护。你有一个互斥量,但你没有在
isEmpty()
中使用它。记录该连接,这很重要,不要迷失方向。此外,对 CV 执行相同的操作,在发出信号时进行记录。 - 关于
isEmpty()
,那个功能反正没用。即使队列在某个时间点不为空,也没有什么可以阻止它在下一秒变空。 - 重新阅读
unique_lock
的文档。你的使用方式比必要的更复杂。 - CV 的用途也很奇怪:通常,您用它来通知服务员变化。你在一个似乎只查询某些状态的函数中无条件地发出信号。