走出锁的误区 - 正面认识锁
2010-09-01 23:31
218 查看
多线程编程,锁通常是必不可少的保证代码运行安全的工具,一提到锁,最直接想到的是性能问题,给人的印象是锁会影响系统性能。这固然不然。但性能本身并不是锁本身引起的,锁也只是一个系统调用,它本身的开销是很小的,很多测试中,我们发现加锁和去掉锁后的性能几乎没有差别,为什么了?
问题的关键在于,锁带来的性能下降,是因为锁与锁之间发生了碰撞,如果没有锁间的碰撞,则它所损害的性能是非常有限的。因此,要想减少因为使用锁带来的性能问题,就必须想办法减少锁之间的碰撞。
我常使用两种方法来降低锁之间的碰撞概率:
1.将需要锁保证的资源分组,将一个大锁化为以组为单位的小锁,如:建立多个队列,每个队列对应的一把锁,这样锁队列时,就不至于锁住所有队列(这里有点类似于数据库中的表锁、行锁等);
2.获取共享资源后即释放锁。这里又有两种场景:一是资源需要重复使用,二是资源取出后不重复使用。对于需要重复使用的应用考虑对该资源使用引用计数,对于不重复的则直接释放锁,如:
示例一:
char* msg = NULL;
if (!_queue.is_empty())
{
sys::CLockHelper<sys::CLock> lock(_lock); // 这里锁助手,能够在作用域结束时自动解锁
msg = _queue.get_message(); // 从共享的队列中取出数据
} // 运行到这里的时候,锁已经解除掉
// 这里使用从队列里取出的msg,如写入文件等
fputs(msg, fp);
示例二:
Object* obj = NULL;
if (!_queue.is_empty())
{
sys::CLockHelper<sys::CLock> lock(_lock); // 这里锁助手,能够在作用域结束时自动解锁
obj = _queue.get_object(); // 从共享的队列中取出数据
obj->inc_refcount(); // 增加引用计数
} // 运行到这里的时候,锁已经解除掉
// 这里可以安全的使用obj了,而且已经不在锁范围之类
// 使用完全,需要放回到锁:
sys::CLockHelper<sys::CLock> lock(_lock);
if (obj->dec_refcount() > 0) // 如果已经没人使用这个obj,则不用再放回队列了,这里也会删除它以释放资源
_queue.push_object(obj);
fputs(msg, fp);
将专文介绍多线程编程定式。通常我都会在论坛里也放一份:http://bbs.hadoopor.com/thread-1824-1-1.html,因为论坛是自己的,可方便数据的备份。
问题的关键在于,锁带来的性能下降,是因为锁与锁之间发生了碰撞,如果没有锁间的碰撞,则它所损害的性能是非常有限的。因此,要想减少因为使用锁带来的性能问题,就必须想办法减少锁之间的碰撞。
我常使用两种方法来降低锁之间的碰撞概率:
1.将需要锁保证的资源分组,将一个大锁化为以组为单位的小锁,如:建立多个队列,每个队列对应的一把锁,这样锁队列时,就不至于锁住所有队列(这里有点类似于数据库中的表锁、行锁等);
2.获取共享资源后即释放锁。这里又有两种场景:一是资源需要重复使用,二是资源取出后不重复使用。对于需要重复使用的应用考虑对该资源使用引用计数,对于不重复的则直接释放锁,如:
示例一:
char* msg = NULL;
if (!_queue.is_empty())
{
sys::CLockHelper<sys::CLock> lock(_lock); // 这里锁助手,能够在作用域结束时自动解锁
msg = _queue.get_message(); // 从共享的队列中取出数据
} // 运行到这里的时候,锁已经解除掉
// 这里使用从队列里取出的msg,如写入文件等
fputs(msg, fp);
示例二:
Object* obj = NULL;
if (!_queue.is_empty())
{
sys::CLockHelper<sys::CLock> lock(_lock); // 这里锁助手,能够在作用域结束时自动解锁
obj = _queue.get_object(); // 从共享的队列中取出数据
obj->inc_refcount(); // 增加引用计数
} // 运行到这里的时候,锁已经解除掉
// 这里可以安全的使用obj了,而且已经不在锁范围之类
// 使用完全,需要放回到锁:
sys::CLockHelper<sys::CLock> lock(_lock);
if (obj->dec_refcount() > 0) // 如果已经没人使用这个obj,则不用再放回队列了,这里也会删除它以释放资源
_queue.push_object(obj);
fputs(msg, fp);
将专文介绍多线程编程定式。通常我都会在论坛里也放一份:http://bbs.hadoopor.com/thread-1824-1-1.html,因为论坛是自己的,可方便数据的备份。
相关文章推荐
- 走出锁的误区 - 正面认识锁
- 走出基金分红的认识误区
- McAfee 的基本规则设置 (走出误区――重新认识端口规则)
- 当前银行股的认识误区(下)
- 走出安全误区之谁能保护Web应用
- 建模的误区—— 走出一般性的设计误区,迈向成功之途
- 企业服务总线的10大认识误区
- ASP.NET新手技术上的认识的误区
- 毕业论文-电子商务罪在何处?--浅谈有关电子商务认识的几个误区
- Redis几个认识误区(Tim总结)
- [转]Redis几个认识误区
- 关于大家对U盘病毒认识误区的纠正及轻松对付U盘病毒的方法
- 软件测试的认识误区
- 中国人对科学的认识误区:从李约瑟难题到钱学森之问
- 走出“搜索引擎营销”三个误区
- Redis几个认识误区
- 当前银行股的认识误区(中)
- 认识误区:断章取义
- [转]Redis几个认识误区
- 女人请走出美容护肤的误区! - 生活至上,美容至尚!