原创 数据库开发技术 作者:liiinuuux 时间:2016-09-26 13:14:25 473 0
利用 shared_ptr可以实现“读不阻塞写”。过程中每次读取不需要拷贝数据,而只需要在要写的时候拷贝一份数据:
点击(此处)折叠或打开
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class mutex_lock: public boost::noncopyable
{
public:
mutex_lock(){pthread_mutex_init(&_mutex, NULL);}
~mutex_lock(){pthread_mutex_destroy(&_mutex);}
void lock() {pthread_mutex_lock(&_mutex);}
void unlock() {pthread_mutex_unlock(&_mutex);}
private:
pthread_mutex_t _mutex;
};
class mutex_locker: public boost::noncopyable
{
public:
explicit mutex_locker(mutex_lock& lk): _lk(lk){_lk.lock();}
~mutex_locker(){_lk.unlock();}
private:
mutex_lock& _lk;
};
// 负责都和写的对象
class rwobj
{
public:
rwobj(){sp_data = boost::make_shared
void read_data()
{
boost::shared_ptr
{
cout << "--------------------- read wait" << endl;
mutex_locker lk(l); // 临界区足够小,适合用mutex。
sp = sp_data; // 利用局部的shared_ptr来增加数据的引用计数,告诉写线程不要修改这份数据
cout << "read sleep 1" << endl;
sleep(1); // 为了阻塞其它线程
}
cout << "read size " << sp->size() << endl;
cout << "read sleep 2" << endl;
sleep(2);
}
void write_data(int i)
{
{
cout << "------------------------------ write wait" << endl;
mutex_locker lk(l); // 写线程的临界区比较大
if(!sp_data.unique())
{
// 如果sp_data引用计数大于1,说明有其他线程在读(通过read_data()提升了引用计数)。
// 此时将数据复制一份,再利用reset或者swap让sp_data指向新数据,老数据让读线程继续读。
// 这个写线程现在独占了sp_data,而之前那份数据在所有读线程读完之后,引用计数会变成0,被最后一个读线程自动析构。
sp_data.reset(new vector
cout << "-------------------------------- copy on write" << endl;
}
sp_data->push_back(i);
}
cout << "sleep write" << endl;
sleep(1);
}
private:
boost::shared_ptr
mutex_lock l;
};
rwobj obj;
// 读线程
void* read_thread(void* arg)
{
while(1)
{
obj.read_data();
}
}
写线程
void* write_thread(void* arg)
{
int i = 1;
while(1)
{
obj.write_data(i++);
}
}
int main()
{
pthread_t thread1,thread2, thread3;
pthread_create(&thread1, NULL, &read_thread, NULL );
pthread_create(&thread2, NULL, &read_thread, NULL );
pthread_create(&thread3, NULL, &write_thread, NULL );
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
pthread_join(thread3,NULL);
return 0;
}