锁粒度

锁粒度

原文出处:

https://www.ibm.com/support/knowledgecenter/zh/ssw_aix_71/com.ibm.aix.performance/lock_granularity.htm

一个在多处理器环境中工作的程序员必须决定对共享数据一定要创建多少单独的锁。如果只有一个锁来序列化整个共享数据项的集合,那么相比之下很可能出现锁争用。广泛使用锁的存在给系统吞吐量加了上限。

如果每一个不同的数据项都有自己的锁,那么两个线程争用这个锁的概率相对来说就比较低。然而,每一个附加的锁定和解锁调用都会消耗处理器时间,并且多个锁的存在使得可能发生死锁。最简单的死锁情况如下图所示,其中线程 1 拥有锁定 A 并且正在等待锁定 B。同时,线程 2 拥有锁定 B 并且正在等待锁定 A。这两个程序都永远用不上会打破死锁的 unlock() 调用。通常对死锁的预防措施是建立一个协议,根据该协议,所有使用一个指定的锁集合的程序必须始终按照完全相同的顺序获得它们。

图 1. 死锁. 上图所示是一个死锁,其中名为线程 1 的列拥有锁定 A,并且正在等待锁定 B。同时,名为线程 2 的列拥有锁定 B,并且正在等待锁定 A。这两个程序线程都永远用不上会打破死锁的解锁调用。

死锁

根据排队理论,一个资源闲置得越少,要得到它的平均等待时间就越长。这种关系是非线性的;如果锁的个数翻倍,平均等待这个锁的时间就比原来的两倍还要多。

减少对锁的等待时间的最有效方法是减少这个锁所保护的范围大小。下面是一些准则:

  • 减少对任何锁的请求频率。
  • 只锁定访问共享数据的代码,而不是一个组件的所有代码(这将减少锁的持有时间)。
  • 只锁定特定的数据项或结构,而不是整个例程。
  • 始终将锁和特定的数据项或结构关联起来,而不是和例程关联。
  • 对于大的数据结构,为结构的每一元素选择一个锁,而不是为整个结构选择一个锁。
  • 当持有一个锁时,从不执行同步 I/O 或者任何其他阻塞活动。
  • 如果您对您组件中的同一数据有多个访问,请试着将它们移到一起,以便它们可以包含在一个锁定 - 解锁操作中。
  • 避免双唤醒的情况。如果您在一个锁下修改了一些数据,并且不得不通知某人您做了这件事,那么在公布唤醒之前请释放该锁。
  • 如果必须同时持有两个锁,那么最后请求那个最忙的锁。

另一方面,过细粒度将增加对锁的请求和释放的频率,因而会增加额外的指令。您必须在过细和过粗粒度之间找到平衡。最佳粒度不得不通过试验和错误找到,这也是一个 MP 系统中的最大挑战之一。下图显示了锁的吞吐量和粒度之间的关系。

图 2. 吞吐量与粒度之间的关系. 这个图是一个简单的双坐标轴图表。垂直轴或 y 轴表示吞吐量。水平轴或 x 轴表示粒度,沿着坐标标尺向外移动时粒度从精细到粗糙而变化。一条延长的贝尔曲线表明了粒度对吞吐量的关系。随着粒度从精细到粗糙,吞吐量逐渐增加到一个最大水平,然后开始慢慢下降。这表明为了达到最大吞吐量,必须在粒度上折衷。

吞吐量与粒度之间的关系

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值