在c++队列中使用pop和visit实现线程安全
thread safe with pop and visit in c++ queue
我知道std::queue不是线程安全的,但我不想锁定队列。所以我用pop&限制使用。
例如,当我想弹出:我有一个枚举来表示第一个元素状态
enum {
Busy = 1,
Unused,
}
当我向队列添加elment时:
void UserAdd() {
lock.lock();
element.status = BUSY;
queue.push_back(element);
lock.unlock();
}
当我访问时:
//only visit function, and every element only called once.
void UserVisit() {
auto header = queue.front();
.......
queue.front().status = UNUSED;
return ;
}
当我想弹出元素时,我会判断第一个元素的状态。
如果第一个元素是Busy,请等待;
如果第一个元素为"未使用",则弹出;
void UserPop() {
while (queue.front().status != Unused) {
usleep(200);
}
lock.lock();
queue.pop();
lock.unlock();
}
线程A:1。UserAdd,2。UserVisit,1.UserAdd,2.UserVisit循环。。。
螺纹B:1。UserPop。
是UserPop((&;UserVisit线程安全?。
我认为它是线程安全的。
无线程安全
请注意,成员函数pop()
确实修改了队列。如果多个线程同时调用UserPop()
,则一个线程可以通过在其上调用pop()
来修改队列,同时另一个线程通过调用front()
:来读取队列
void UserPop() {
while (queue.front().status != Unused) { // <-- read queue
usleep(200);
}
queue.pop(); // <-- modify queue
}
由于队列本身std::queue
不为您处理并发访问,因此UserPop()
不是线程安全的。
确保线程安全
使其线程安全的一个简单方法是在读取或修改队列时添加一个互斥锁并对其进行锁定:
std::mutex mtx;
// ...
void UserPop() {
std::unique_lock<std::mutex> lck(mtx);
// mtx is locked at this point
while (queue.front().status != Unused) {
lck.unlock();
usleep(200); // mtx is not locked
lck.lock();
}
// mtx is locked at this point
queue.pop();
}
std::queue
的成员函数front()
和pop()
在持有互斥锁时总是被调用。
但是,您可能需要考虑使用std::condition_variable
。它提供了对繁忙等待的优化:
std::mutex mtx;
std::condition_variable cv;
void UserPop() {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [this]() { return queue.front().status == Unused; });
queue.pop();
}
相关文章:
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- std::visit无法识别类型
- 使用GSoap实现ONVIF
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 用于AVX的ln(x)的实现,m256
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 在c++队列中使用pop和visit实现线程安全