shared_ptr实现多线程读写copy-on-write

利用boost的shared_ptr可以实现“读不阻塞写 ”。过程中每次读取不需要拷贝数据,而只需要在要写的时候拷贝一份数据:

点击( 此处 )折叠或打开
  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <map>
  4. #include <vector>
  5. #include <boost/smart_ptr.hpp>
  6. #include <boost/make_shared.hpp>
  7. #include <boost/enable_shared_from_this.hpp>
  8. #include <boost/bind.hpp>
  9. #include <boost/function.hpp>
  10. #include <boost/noncopyable.hpp>

  11. #include <pthread.h>
  12. #include <unistd.h>

  13. using namespace std;


  14. class mutex_lock: public boost::noncopyable
  15. {
  16. public:
  17.     mutex_lock(){pthread_mutex_init(&_mutex, NULL);}
  18.     ~mutex_lock(){pthread_mutex_destroy(&_mutex);}
  19.     void lock() {pthread_mutex_lock(&_mutex);}
  20.     void unlock() {pthread_mutex_unlock(&_mutex);}
  21. private:
  22.     pthread_mutex_t _mutex;
  23. };

  24. class mutex_locker: public boost::noncopyable
  25. {
  26. public:
  27.     explicit mutex_locker(mutex_lock& lk): _lk(lk){_lk.lock();}
  28.     ~mutex_locker(){_lk.unlock();}
  29. private:
  30.     mutex_lock& _lk;
  31. };


  32. // 负责都和写的对象
  33. class rwobj
  34. {
  35. public:
  36.     rwobj(){sp_data = boost::make_shared<vector<int> >();}
  37.     void read_data()
  38.     {
  39.         boost::shared_ptr<vector<int> > sp;
  40.         {
  41.             cout << "--------------------- read wait" << endl;
  42.             mutex_locker lk(l); // 临界区足够小,适合用mutex。
  43.             sp = sp_data; // 利用局部的shared_ptr来增加数据的引用计数,告诉写线程不要修改这份数据
  44.             cout << "read sleep 1" << endl;
  45.             sleep(1); // 为了阻塞其它线程
  46.         }

  47.         cout << "read size " << sp->size() << endl;
  48.         cout << "read sleep 2" << endl;
  49.         sleep(2);
  50.     }

  51.     void write_data(int i)
  52.     {
  53.         {
  54.             cout << "------------------------------ write wait" << endl;
  55.             mutex_locker lk(l); // 写线程的临界区比较大
  56.             if(!sp_data.unique())
  57.             {
  58.                 // 如果sp_data引用计数大于1,说明有其他线程在读(通过read_data()提升了引用计数)。
  59.                 // 此时将数据复制一份,再利用reset或者swap让sp_data指向新数据,老数据让读线程继续读。
  60.                 // 这个写线程现在独占了sp_data,而之前那份数据在所有读线程读完之后,引用计数会变成0,被最后一个读线程自动析构。
  61.                 sp_data.reset(new vector<int>(*sp_data));
  62.                 cout << "-------------------------------- copy on write" << endl;
  63.             }
  64.             sp_data->push_back(i);
  65.         }
  66.         cout << "sleep write" << endl;
  67.         sleep(1);
  68.     }
  69. private:
  70.     boost::shared_ptr<vector<int> > sp_data;
  71.     mutex_lock l;
  72. };


  73. rwobj obj;

  74. // 读线程
  75. void* read_thread(void* arg)
  76. {
  77.     while(1)
  78.     {
  79.         obj.read_data();
  80.     }
  81. }

  82. 写线程
  83. void* write_thread(void* arg)
  84. {
  85.     int i = 1;
  86.     while(1)
  87.     {
  88.         obj.write_data(i++);
  89.     }
  90. }

  91. int main()
  92. {
  93.     pthread_t thread1,thread2, thread3;
  94.     pthread_create(&thread1, NULL, &read_thread, NULL );
  95.     pthread_create(&thread2, NULL, &read_thread, NULL );
  96.     pthread_create(&thread3, NULL, &write_thread, NULL );
  97.     pthread_join(thread1,NULL);
  98.     pthread_join(thread2,NULL);
  99.     pthread_join(thread3,NULL);
  100.     return 0;
  101. }





来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26239116/viewspace-2125592/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26239116/viewspace-2125592/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值