线程安全堆栈互斥在忙时被破坏 我一直在学习C++标准库多线程的一段时间,作为一个练习,我想使用互斥阻塞和条件变量来做一个线程安全的堆栈。这是我上的课: #ifndef THREADSAFE_STACK_H_ #define THREADSAFE_STACK_H_ #include <mutex> #include <condition_variable> #include <stack> #include <memory> template <typename T> class threadsafe_stack { public: mutable std::mutex mut; std::stack<T> st; std::condition_variable cond; public: threadsafe_stack() = default; threadsafe_stack(const threadsafe_stack &s); threadsafe_stack(threadsafe_stack &&s); threadsafe_stack& operator=(const threadsafe_stack &s); threadsafe_stack& operator=(threadsafe_stack &&s); void push(const T &t); void push(T &&t); bool try_pop(T &t); std::shared_ptr<T> try_pop(); void wait_and_pop(T &t); std::shared_ptr<T> wait_and_pop(); typename std::stack<T>::size_type size() const; bool empty() const; }; template <typename T> threadsafe_stack<T>::threadsafe_stack(const threadsafe_stack &s) { std::lock(mut, s.mut); std::lock_guard<std::mutex> lock1(mut, std::adopt_lock); std::lock_guard<std::mutex> lock2(s.mut, std::adopt_lock); st = s.st; } template <typename T> threadsafe_stack<T>::threadsafe_stack(threadsafe_stack &&s) { std::lock(mut, s.mut); std::lock_guard<std::mutex> lock1(mut, std::adopt_lock); std::lock_guard<std::mutex> lock2(s.mut, std::adopt_lock); st = std::move(s.st); } template <typename T> threadsafe_stack<T>& threadsafe_stack<T>::operator=(const threadsafe_stack &s) { if (this == &s) return *this; std::lock(mut, s.mut); std::lock_guard<std::mutex> lock1(mut, std::adopt_lock); std::lock_guard<std::mutex> lock2(s.mut, std::adopt_lock); s = s.st; return *this; } template <typename T> threadsafe_stack<T>& threadsafe_stack<T>::operator=(threadsafe_stack &&s) { std::lock(mut, s.mut); std::lock_guard<std::mutex> lock1(mut, std::adopt_lock); std::lock_guard<std::mutex> lock2(s.mut, std::adopt_lock); s = std::move(s.st); } template <typename T> void threadsafe_stack<T>::push(const T &t) { std::lock_guard<std::mutex> lock(mut); st.push(t); cond.notify_one(); } template <typename T> void threadsafe_stack<T>::push(T &&t) { std::lock_guard<std::mutex> lock(mut); st.push(std::move(t)); cond.notify_one(); } template <typename T> bool threadsafe_stack<T>::try_pop(T &t) { std::lock_guard<std::mutex> lock(mut); if (st.empty()) return false; t = st.top(); st.pop(); return true; } template <typename T> std::shared_ptr<T> threadsafe_stack<T>::try_pop() { std::lock_guard<std::mutex> lock(mut); if (st.empty()) return std::shared_ptr<T>(); std::shared_ptr<T> result(new T{st.top}); st.pop(); return result; } template <typename T> void threadsafe_stack<T>::wait_and_pop(T &t) { std::unique_lock<std::mutex> lock(mut); cond.wait(lock, [this]{ return !st.empty(); }); t = st.top(); st.pop(); } template <typename T> std::shared_ptr<T> threadsafe_stack<T>::wait_and_pop() { std::unique_lock<std::mutex> lock(mut); cond.wait(lock, [this]{ return !st.empty(); }); std::shared_ptr<T> result(new T{ st.top }); st.pop(); return result; } template <typename T> typename std::stack<T>::size_type threadsafe_stack<T>::size() const { std::lock_guard<std::mutex> lock(mut); return st.size(); } template <typename T> bool threadsafe_stack<T>::empty() const { std::lock_guard<std::mutex> lock(mut); return st.empty(); } #endif
第二行在我按下任意键或尝试关闭控制台后立即出现。伴随着额外的消息,我得到了一个错误(我猜是未处理的异常?),在我看来,在我退出程序时,似乎正在使用互斥锁,但它不应该被使用,因为条件变量wait应该在等待时解锁它。我不知道。发生这种情况是因为程序退出,这会破坏全局变量。如果要等待程序完成工作,则需要加入底部的线程安全堆栈互斥在忙时被破坏 我一直在学习C++标准库多线程的一段时间,作为一个练习,我想使用互斥阻塞和条件变量来做一个线程安全的堆栈。这是我上的课: #ifndef THREADSAFE_STACK_H_ #define THREADSAFE_STACK_H_ #include <mutex> #include <condition_variable> #include <stack> #include <memory> template <typename T> class threadsafe_stack { public: mutable std::mutex mut; std::stack<T> st; std::condition_variable cond; public: threadsafe_stack() = default; threadsafe_stack(const threadsafe_stack &s); threadsafe_stack(threadsafe_stack &&s); threadsafe_stack& operator=(const threadsafe_stack &s); threadsafe_stack& operator=(threadsafe_stack &&s); void push(const T &t); void push(T &&t); bool try_pop(T &t); std::shared_ptr<T> try_pop(); void wait_and_pop(T &t); std::shared_ptr<T> wait_and_pop(); typename std::stack<T>::size_type size() const; bool empty() const; }; template <typename T> threadsafe_stack<T>::threadsafe_stack(const threadsafe_stack &s) { std::lock(mut, s.mut); std::lock_guard<std::mutex> lock1(mut, std::adopt_lock); std::lock_guard<std::mutex> lock2(s.mut, std::adopt_lock); st = s.st; } template <typename T> threadsafe_stack<T>::threadsafe_stack(threadsafe_stack &&s) { std::lock(mut, s.mut); std::lock_guard<std::mutex> lock1(mut, std::adopt_lock); std::lock_guard<std::mutex> lock2(s.mut, std::adopt_lock); st = std::move(s.st); } template <typename T> threadsafe_stack<T>& threadsafe_stack<T>::operator=(const threadsafe_stack &s) { if (this == &s) return *this; std::lock(mut, s.mut); std::lock_guard<std::mutex> lock1(mut, std::adopt_lock); std::lock_guard<std::mutex> lock2(s.mut, std::adopt_lock); s = s.st; return *this; } template <typename T> threadsafe_stack<T>& threadsafe_stack<T>::operator=(threadsafe_stack &&s) { std::lock(mut, s.mut); std::lock_guard<std::mutex> lock1(mut, std::adopt_lock); std::lock_guard<std::mutex> lock2(s.mut, std::adopt_lock); s = std::move(s.st); } template <typename T> void threadsafe_stack<T>::push(const T &t) { std::lock_guard<std::mutex> lock(mut); st.push(t); cond.notify_one(); } template <typename T> void threadsafe_stack<T>::push(T &&t) { std::lock_guard<std::mutex> lock(mut); st.push(std::move(t)); cond.notify_one(); } template <typename T> bool threadsafe_stack<T>::try_pop(T &t) { std::lock_guard<std::mutex> lock(mut); if (st.empty()) return false; t = st.top(); st.pop(); return true; } template <typename T> std::shared_ptr<T> threadsafe_stack<T>::try_pop() { std::lock_guard<std::mutex> lock(mut); if (st.empty()) return std::shared_ptr<T>(); std::shared_ptr<T> result(new T{st.top}); st.pop(); return result; } template <typename T> void threadsafe_stack<T>::wait_and_pop(T &t) { std::unique_lock<std::mutex> lock(mut); cond.wait(lock, [this]{ return !st.empty(); }); t = st.top(); st.pop(); } template <typename T> std::shared_ptr<T> threadsafe_stack<T>::wait_and_pop() { std::unique_lock<std::mutex> lock(mut); cond.wait(lock, [this]{ return !st.empty(); }); std::shared_ptr<T> result(new T{ st.top }); st.pop(); return result; } template <typename T> typename std::stack<T>::size_type threadsafe_stack<T>::size() const { std::lock_guard<std::mutex> lock(mut); return st.size(); } template <typename T> bool threadsafe_stack<T>::empty() const { std::lock_guard<std::mutex> lock(mut); return st.empty(); } #endif,c++,multithreading,thread-safety,stack,mutex,C++,Multithreading,Thread Safety,Stack,Mutex,第二行在我按下任意键或尝试关闭控制台后立即出现。伴随着额外的消息,我得到了一个错误(我猜是未处理的异常?),在我看来,在我退出程序时,似乎正在使用互斥锁,但它不应该被使用,因为条件变量wait应该在等待时解锁它。我不知道。发生这种情况是因为程序退出,这会破坏全局变量。如果要等待程序完成工作,则需要加入底部的处理器线程(而不是将其分离) 条件变量只能使另一个线程休眠,而不能使主线程休眠。如果唯一使用互斥锁的是单个进程,则应使用关键部分。MSDN:“…临界截面对象提供了一种更快、更有效的互斥机制”-
处理器
线程(而不是将其分离)
条件变量只能使另一个线程休眠,而不能使主线程休眠。如果唯一使用互斥锁的是单个进程,则应使用
关键部分。MSDN:“…临界截面对象提供了一种更快、更有效的互斥机制”-只是sayinOh noes,它的速度非常快?据我所知,互斥在Windows上是作为critsec实现的。@pappy Golly。那么,如果我真的想要一个互斥锁“保护共享资源不被多个线程或进程同时访问”,std::该怎么办?@MickyDuncan:可能什么都没有。该标准没有说明进程间通信或同步。@Puppy好的,谢谢Puppy
#include <iostream>
#include <condition_variable>
#include <ctime>
#include <chrono>
#include <thread>
#include "threadsafe_stack.h"
threadsafe_stack<int> data_stack;
void process_data()
{
while (true)
{
int val = 0;
data_stack.wait_and_pop(val);
std::cout << val << " ";
}
}
int main()
{
std::thread processor(process_data);
processor.detach();
int values[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int i = 0; i < 10; i++)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
data_stack.push(values[i]);
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
system("pause");
return 0;
}
1 2 3 4 5 6 7 8 9 10 Press any key to continue . . .
f:\dd\vctools\crt\crtw32\stdcpp\thr\mutex.c(40): mutex destroyed while busy