我处理多线程项目,C++,我怀疑有关的std ::互斥避免竞争条件下使用std ::互斥
让我们假设我有一个堆栈。
#include <exception>
#include <memory>
#include <mutex>
#include <stack>
struct empty_stack: std::exception
{
const char* what() const throw();
};
template<typename T>
class threadsafe_stack
{
private:
std::stack<T> data;
mutable std::mutex m;
public:
threadsafe_stack(){}
threadsafe_stack(const threadsafe_stack& other)
{
std::lock_guard<std::mutex> lock(other.m);
data=other.data;
}
threadsafe_stack& operator=(const threadsafe_stack&) = delete;
void push(T new_value)
{
std::lock_guard<std::mutex> lock(m);
data.push(new_value);
}
std::shared_ptr<T> pop()
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
std::shared_ptr<T> const res(std::make_shared<T>(data.top()));
data.pop();
return res;
}
void pop(T& value)
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
value=data.top();
data.pop();
}
bool empty() const
{
std::lock_guard<std::mutex> lock(m);
return data.empty();
}
};
有人说使用这个堆栈可以避免竞争条件。不过,我认为这里的问题是,这里的互斥体互斥只能保证单个功能不在一起。例如,我可以让线程调用push和pop。那些功能还存在竞争状况的问题。
例如:
threadsafe_stack st; //global varibale for simple
void fun1(threadsafe_stack st)
{
std::lock_guard<std::mutex> lock(m);
st.push(t);
t = st.pop();
//
}
void fun2(threadsafe_stack st)
{
std::lock_guard<std::mutex> lock(m);
T t,t2;
t = st.pop();
// Do big things
st.push(t2);
//
}
如果一个线程FUN1和FUN2调用相同的堆(全局变量进行简单)。所以它可以是一个竞争条件(?)
我只有解决方案我可以认为是使用某种原子事务手段,而不是直接调用push(),pop(),empty(),我打电话给他们通过函数带有一个“函数指针”,这些函数只有一个互斥量。
例如:
#define PUSH 0
#define POP 1
#define EMPTY 2
changeStack(int kindOfFunction, T* input, bool* isEmpty)
{
std::lock_guard<std::mutex> lock(m);
switch(kindOfFunction){
case PUSH:
push(input);
break;
case POP:
input = pop();
break;
case EMPTY:
isEmpty = empty();
break;
}
}
是我的解决方案好?或者我只是过分追求,我的朋友告诉我的第一个解决方案就够了吗?有没有其他解决方案呢?解决方案可以避免像我所说的“原子事务”。
为什么您认为如果从线程调用弹出/会有比赛条件?线程A调用push和阻塞互斥体,线程B调用pop并等待,直到互斥体被push解除阻塞。 – ForEveR
你正试图解决一个没有问题。“互斥互斥这里只确保个人功能不在一起。” ---这是错误的假设。 –