文章目录
本笔记仅供个人复习所用!!!!
很感谢原作者Anthony Williams,为我提供了一条C++多线程开发的学习捷径,本书中提供了很多关于多线程开发的问题解决方案,是一本好书!
用代码(互斥量mutex)保护共享数据常见错误
- 切勿将受保护数据传递到互斥锁作用域之外
- 切勿将受保护的数据以参数的形式传递到用户函数中去
线程安全问题-拷贝构造异常(内存分配失败)
-
传入一个引用
通过引用来获取想要的值缺点:
-
需要临时构造一个实例,从时间和资源的角度看不划算
-
需要可赋值的存储类型,因为要通过给传入的引用赋值来获取数据,很多用户自定义的类型可能都不支持赋值操作
-
-
无异常抛出的拷贝构造函数或移动构造函数
-
返回指向数据的指针
优势:
自由拷贝,不会发异常缺点:
指针的内存分配管理繁琐(new&&delete),解决方案:使用std::share_ptr
能很好的避免内存泄漏 -
上述解决方案混合使用
线程安全的堆栈代码实现:
#include<exception>
#include<memory>//For std::shared_ptr<>
struct empty_stack: std::exception{
constchar* what()constthrow();
};
template<typename T>
class threadsafe_stack{
public:
threadsafe_stack();
threadsafe_stack(const threadsafe_stack&);
threadsafe_stack& operator=(const threadsafe_stack&)=delete//删除赋值操作
void push(T new_value);
std::shared_ptr<T> pop();
void pop(T& value);
bool empty()const;//当stack为空时抛出异常
};
**削减接口可以获得最大限度的安全与数据控制(五个操作->三个操作)**
线程安全的堆栈内部操作实现:
#include <exception>
#inlcude <mutex>
#include <stack>
#include <memory>
struct empty_stack:std::exception{
constchar* what() constthrow{
return "empty stack!";
}
}
template <typename T>
class threadsafe_stack{
private:
std::stack<T> data;
mutable std::mutex m;
public:
threadsafe_stack():data(stack<T>()){};
threadsafe_stack(const threadsafe_stack& other){
std::lock_guard<std::mutex>lock(other.m);//给other对象加锁,保证赋值过程中数据的安全
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::share_ptr pop(){
std::lock_guard<std::mutex>lock(m);
if(data.empty())
throw empty_stack();
std::share_ptr<T>const res(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();
}
}
};
线程安全的堆栈(改进版)
#ifndef THRAEDSAFE_STACK_HPP
#define THRAEDSAFE_STACK_HPP
#include <mutex>
#include <condition_variable>
#include <stack>
#include <memory>
template<typename T>
class threadsafe_stack
{
private:
mutable std::mutex mut;
std::stack<T> data_stack;
std::condition_variable data_cond;
public:
threadsafe_stack()
{}
threadsafe_stack(threadsafe_stack const& other)
{
std::lock_guard<std::mutex> lk(other.mut);
data_stack=other.data_stack;
}
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_stack.push(new_value);
data_cond.notify_one();
}
void wait_and_pop(T& value)//等待pop返回引用版
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_stack.empty();});
value=data_stack.top();
data_queue.pop();
}
std::shared_ptr<T> wait_and_pop()//等待pop返回智能指针版
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_stack.empty();});
std::shared_ptr<T> res(std::make_shared<T>(data_stack.top()));
data_queue.pop();
return res;
}
bool try_pop(T& value)//尝试pop返回引用版
{
std::lock_guard<std::mutex> lk(mut);
if(data_stack.empty())
return false;
value=data_stack.top();
data_stack.pop();
return true;
}
std::shared_ptr<T> try_pop()//尝试pop返回智能指针版
{
std::lock_guard<std::mutex> lk(mut);
if(data_stack.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res(std::make_shared<T>(data_stack.top()));
data_stack.pop();
return res;
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_stack.empty();
}
};
#endif