C++安全并发访问容器元素

一个库可能试图以下列方式实现这样完全线程安全的容器:
1、在每次调用容器的成员函数期间都要锁定该容器。
2、在每个容器返回的迭代器(例如通过调用begin或end)的生存期之内都要锁定该容器。
3、在每个在容器上调用的算法执行期间锁定该容器。(这事实上没有意义,因为,正如条款32所解释的,算法没有办法识别出它们正在操作的容器。不过,我们将在这里检验这个选项,因为它的教育意义在于看看为什么即使是可能的它也不能工作。)

标准库STL的vector, deque, list等等不是线程安全的。例如 线程1正在使用迭代器(iterator)读vector,线程2正在对该vector进行插入操作,使vector重新分配内存,这样就造成线程1中的迭代器失效。
多个线程读是安全的,在读的过程中,不能对容器有任何写入操作
多个线程可以同时对不同的容器做写入操作。
不能指望任何STL实现来解决线程难题,必须手动做同步控制.

方案1 对vector进行加锁处理

effective STL给出的Lock框架

template<typename Container> //一个为容器获取和释放互斥体的模板  
class Lock
{ //框架;其中的很多细节被省略了  
public:
	Lock(const Container& container) :c(container) 
	{  
		getMutexFor(c); 
		//在构造函数中获取互斥体 
	} 
	~Lock() 
	{   
		releaseMutexFor(c); 
		//在析构函数中释放它
	} 
private: const Container& c; 
};  

方案2 微软的Parallel Patterns Library (PPL)

看MSDN
PPL 提供的功能

1 Task Parallelism: a mechanism to execute several work items (tasks) in parallel
任务并行:一种并行执行若干工作项(任务)的机制

2 Parallel algorithms: generic algorithms that act on collections of data in parallel
并行算法:并行作用于数据集合的泛型算法

3 Parallel containers and objects: generic container types that provide safe concurrent access to their elements
并行容器和对象:提供对其元素的安全并发访问的泛型容器类型。
并行计算是
使用 PPL Concurrency::parallel_for_each 算法
结果存储在 Concurrency::concurrent_vector 对象中。

// parallel-fibonacci.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <concurrent_vector.h>
#include <array>
#include <vector>
#include <tuple>
#include <algorithm>
#include <iostream>
 
 
using namespace Concurrency;
using namespace std;
 
 
// Calls the provided work function and returns the number of milliseconds 
// that it takes to call that function.
template <class Function>
__int64 time_call(Function&& f)
{
   __int64 begin = GetTickCount();
   f();
   return GetTickCount() - begin;
}
 
 
// Computes the nth Fibonacci number.
int fibonacci(int n)
{
   if(n < 2)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}
 
 
int wmain()
{
   __int64 elapsed;
 
 
   // An array of Fibonacci numbers to compute.
   array<int, 4> a = { 24, 26, 41, 42 };
 
 
   // The results of the serial computation.
   vector<tuple<int,int>> results1;
 
 
   // The results of the parallel computation.
   concurrent_vector<tuple<int,int>> results2;
 
 
   // Use the for_each algorithm to compute the results serially.
   elapsed = time_call([&] 
   {
      for_each (a.begin(), a.end(), [&](int n) {
         results1.push_back(make_tuple(n, fibonacci(n)));
      });
   });   
   wcout << L"serial time: " << elapsed << L" ms" << endl;
 
 
   // Use the parallel_for_each algorithm to perform the same task.
   elapsed = time_call([&] 
   {
      parallel_for_each (a.begin(), a.end(), [&](int n) {
         results2.push_back(make_tuple(n, fibonacci(n)));
      });
 
 
      // Because parallel_for_each acts concurrently, the results do not 
      // have a pre-determined order. Sort the concurrent_vector object
      // so that the results match the serial version.
      sort(results2.begin(), results2.end());
   });   
   wcout << L"parallel time: " << elapsed << L" ms" << endl << endl;
 
 
   // Print the results.
   for_each (results2.begin(), results2.end(), [](tuple<int,int>& pair) {
      wcout << L"fib(" << get<0>(pair) << L"): " << get<1>(pair) << endl;
   });
}

方案3 Intel TBB(Threading Building Blocks)
Intel TBB 提供的功能
1 直接使用的线程安全容器,比如 concurrent_vector 和 concurrent_queue。
2 通用的并行算法,如 parallel_for 和 parallel_reduce。
3 模板类 atomic 中提供了无锁(Lock-free或者mutex-free)并发编程支持。

方案4 无锁数据结构支持库Concurrent Data Structures (libcds).
地址 http://sourceforge.net/projects/libcds/
https://github.com/khizmax/libcds/tree/master/test/unit
下载以后里面直接有从VC2008到VC2013的编译环境,依赖于boost库

方案5 Boost 使用boost.lockfree

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值