C++11 并发实战阅读笔记(2)

第三章


#include 
#include 
#include 
std::list some_list;
std::mutex some_mutex;
void add_to_list(int new_value)
{
   std::lock_guard guard(some_mutex);   // std::lock_guard 是RAII用法
   some_list.push_back(new_value);
}
bool list_contains(int value_to_find)
{
   std::lock_guard guard(some_mutex);
   return std::find(some_list.begin(),some_list.end(),value_to_find)
   != some_list.end();
}
上面没啥好讲的。。常规用法,就是用了一个RAII


class some_data
{
  int a;
  std::string b;
  public:
  void do_something();
};
class data_wrapper
{
  private:
  some_data data;
  std::mutex m;
  public:
  template
  void process_data(Function func)
  {
    std::lock_guard l(m);
    func(data);
  }
  };
some_data* unprotected;
void malicious_function(some_data& protected_data)
{
  unprotected=&protected_data;
}
data_wrapper x;
void foo()
{
  x.process_data(malicious_function);
  unprotected->do_something();
}
不要在使用了mutex保护的函数返回引用或者指针,这样会使数据失去保护: 
unprotected->do_something();  // 这样就在mutex保护之外访问了数据



#include 
#include 
#include 
#include 
struct empty_stack: std::exception
{
  const char* what() const throw();
};
template
class threadsafe_stack
{
  private:
  std::stack data;
  mutable std::mutex m;
  public:
  threadsafe_stack(){}
  threadsafe_stack(const threadsafe_stack& other)
  {
    std::lock_guard lock(other.m);
    data=other.data;
  }
  threadsafe_stack& operator=(const threadsafe_stack&) = delete;
  void push(T new_value)
  {
    std::lock_guard lock(m);
    data.push(new_value);
  }
  std::shared_ptr pop()
  {
    std::lock_guard lock(m);
    if(data.empty()) throw empty_stack();
    std::shared_ptr const res(std::make_shared(data.top()));
    data.pop();
    return res;
  }
  void pop(T& value)
  {
    std::lock_guard lock(m);
    if(data.empty()) throw empty_stack();
    value=data.top();
    data.pop();
  }
  bool empty() const
  {
    std::lock_guard lock(m);
    return data.empty();
  }
};

这一段书上讲的有点啰嗦,其实按照我自己的理解就是,对stack的所有操作,尤其是连续的操作都必须用mutex锁住,不能只锁单一的一个函数!





你可能感兴趣的:(C++11 并发实战阅读笔记(2))