muduo库学习之线程同步07——CopyOnWrite

本文介绍了CopyOnWrite(COW)技术在并发编程中的应用,通过一个例子展示了如何使用COW和shared_ptr来避免死锁。在read端,通过局部FooListPtr观察者增加引用计数,减少临界区。而在write端,当g_foos不唯一时,创建新副本进行修改,从而实现并发读写的高效和安全。
摘要由CSDN通过智能技术生成

东阳的学习笔记

CopyOnWriter

1 什么是COW?

COW字面意思写时复制,是一种并发场景下的共享数据策略。

顾名思义,它的基本思想是大家共享同一份数据,读的时候不加锁,直接读取数据;更新数据时在其拷贝副本上操作,在这个新拷贝的数据上演绎更新操作,然后再用这个新数据替换老数据

2 借 shared_ptr 实现 copy-on-write

互斥器 那篇文章中提到了一个死锁的例子。在这里我们来看看如何使用 COW 来解决这个问题:

  1. 先将数据结构改成:
typedef std::vector<Foo> Foolist;
typedef boost::shared_ptr<Foolist> FooListPtr;
MutexLock mutex;
FooListPtr g_foos;

2.1 read 端

在read端,使用一个栈上局部 FooListPtr 变量作为一个 观察者 ,它使得共享变量 g_foos 的引用计数增加(防止并发修改)。traverse() 函数的临界区是&4~&8,临界区内只读了一次共享变量 g_foos (多线程并发读写 shared_ptr 必须使用 mutex 保护),比原来的写法大为缩短,而且多个线程同时调用 traverse() 也不会堵塞。

void traverse()
{
		FooListPtr foos;          // 观察者
		{
			MutexLockGuard lock(mutex);
			foos = g_foos;
			assert(!g_foos.unique());
		}
		
		// assert(!g_foos.unique()) 这个断言不成立
		for (std::vector<Foo>::const_iterator it = foos.begin();
		it != foos.end(); ++it)
		{
			it->doit();
		}
}

write 端

关键看 write 端的 post() 怎么写。

  • 如果g_foos.unique()为true,则说明没有线程正在读取,可以放心地原地修改
  • 否则,copy一份,即COW
void post(const Foo& f)
{	
	MutexLockGuard lock(mutex);
	if (!g_foos.unique())    // 其他线程正在读
	{
		g_foos.reset(new FooList(*g_foos));
		printf("copy the whole list");  // 
	}
	assert(g_foos.unique());    // 没有其他线程正在读,原地操作
	foos.push_back(f);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东阳z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值