Lock Convoys

原创 2011年11月15日 17:22:12
 

    Lock Convoys是在多线程并发环境下由于锁的使用而引起的性能退化问题。当多个相同优先级的线程频繁地争抢同一个锁时可能会引起lock convoys问题,一般而言,lock convoys并不会像deadlock或livelock那样造成应用逻辑停止不前,相反地,遭受lock convoys的系统或应用程序仍然往前运行,但是,由于线程们频繁地争抢锁而导致过多的线程环境切换,从而使得系统的运行效率大为降低,而且,若存在同等优先级下不参与锁争抢的线程,则它们可以获得相对较多的处理器资源,从而造成系统调度的不公平性。

本文将解释lock convoys问题的缘由。

 

    假设一组线程在频繁地获取锁(所谓频繁,指在一个时间片的执行周期内多次获取锁),比如在Windows应用程序中常常用临界区(critical section)来保护一个共享变量或者防止一段代码被重入,这是极有可能发生的。假设线程A获取到了锁,这时发生了线程调度中断,它的时间片用完了,于是,系统调度器交给下一个线程执行,不妨设线程B获得了执行权。由于此锁被线程A获取,所以,当线程B执行到获取锁的操作时,虽然时间片未用完,但不得不放弃执行权。如此继续,所有同等优先级且要竞争此锁的线程都被阻塞。调度器再次回到线程A,很快地线程A释放了锁。在操作系统中,释放一个锁,意味着内核中如果有线程正在等待该锁,则它的状态就可以变成运行态。比如,线程B的获取操作成功。但此时,内核只是将线程B标记为锁的所有者,而线程A继续执行。很快地,线程A又要获取锁了,由于该锁已经被标记给线程B了,所以线程A不得不放弃时间片,将控制权交给调度器。调度器终于可以捡起线程B,将处理器的执行权交给它。等到线程B释放了锁,下一个线程获得锁的所有权,并且等到线程B放弃执行权或者结束时间片之后就有机会被执行。此过程一直持续,经过一轮之后又会回到线程A,从而继续下一轮的争抢。在此期间,这些线程总是未执行满时间片就不得不放弃执行权。下面的图说明了三个线程在争抢一个锁时候的执行情况。

<!--[endif]-->

    假设一个线程在一个满时间片的执行过程中要多次获取/释放锁,它一旦释放了锁,则意味着,只要存在锁竞争,它在分配给它的当前时间片内已经无法再重新获得锁了。所以,它只能执行到它的下一次获取操作为止。譬如,参与竞争的线程平均执行1/3时间片就要获取锁,那么,线程的实际执行时间变成了1/3时间片。系统的调度粒度变成原来的1/3时间间隔。这引起了3倍数量的线程切换。从上图的右半部分可以看出,每个线程在一轮的循环中,只有1/3时间片的机会。这导致了3倍的线程切换。

    除了引起调度粒度变小以外,lock convoys的另一个问题是造成调度器的时间分配不公平。假设另有一个线程X也是在同等的优先级上运行,但没有参与锁竞争。于是,在每一轮的锁竞争过程中,线程X都有机会被分配一次完整的时间片,于是,这些竞争的线程在一轮中获得1/3时间片,而非竞争的线程可以获得完整的时间片。当然,你可以说这种不公平是由于它们抢锁而引起的,但从时间分配比例而言,参与竞争与不参与竞争的线程是不公平的。下图说明了线程X和A、B、C之间的执行时间差异。

<!--[endif]-->

    由以上描述可以看出,Lock convoys的存在条件是,参与竞争的线程频繁地获取锁,锁被一个线程释放以后其所有权便落到了另一个线程的手里。在操作系统中,相同优先级的线程按照FIFO的顺序被调度和执行,竞争同一个锁的线程也按照FIFO的顺序被依次成功地获取到锁。这些条件在现代操作系统中都能被满足,包括Windows。

    Lock convoys虽然不是致命的问题,但也可能在实际系统中发生。Sue Loh在她的博客文章[1]中展示了在Windows CE中发生的lock convoy问题。她也讨论了一种合理的缓解lock convoy的方案,要求在每个线程获取锁的时候先尝试(try),如果尝试多次仍不成功,再阻塞。

 

注1:关于lock convoys的介绍资料非常少,在wikipedia上也只有极有限的说明[2],Sue Loh的博客文章[1]有比较详细的说明。我计划在下一篇文章中再讨论lock convoys问题在Windows平台上的表现(以Windows Server 2003 SP1和WRK作为参照)以及线程执行路径。

注2:关于lock convoys的中文翻译,我看到有一本书上将其翻译为“锁护送”。个人感觉不是非常妥当,或许翻译为“锁封护”或“锁护封”好一些。

 

References:

[1] Sue Loh, Lock Convoys and How to Recognize Them, http://blogs.msdn.com/b/sloh/archive/2005/05/27/lock-convoys-and-how-to-recognize-them.aspx, 2005.

[2] Lock Convoys, http://en.wikipedia.org/wiki/Lock_convoy

 

原文链接:http://blog.csdn.net/panaimin/article/details/5981766

临界区、锁竞争(Lock Contention)、锁护送(Lock Convoys)简单分析 盛大创新院 刘刚

临界区是一种防止多个线程同时执行一个特定代码节的机制,window临界区是一种轻量级机制,在某一时间内只允许一个线程执行某个给定代码段。   通常在修改全局数据(如集合类)时会使用临界区。事件、多...
  • mfc_boy
  • mfc_boy
  • 2010-11-10 11:00:00
  • 2596

Lock Convoys Explained

Lock Convoys是在多线程并发环境下由于锁的使用而引起的性能退化问题。当多个相同优先级的线程频繁地争抢同一个锁时可能会引起lock convoys问题,一般而言,lock convoys并...
  • xhjcehust
  • xhjcehust
  • 2015-02-04 09:26:40
  • 476

Linux同步机制 - 基本概念(死锁,活锁,饿死,优先级反转,护航现象)

讲解了Linux Pthread中的一些基本概念,包括,死锁,活锁,饿死,优先级反转,为后面研究锁机制和无锁编程打下基础...
  • linux_bug
  • linux_bug
  • 2015-09-18 10:56:37
  • 1133

C# 设置键盘Num,Caps,Scroll键状态

  • 2013年03月13日 22:52
  • 19KB
  • 下载

lock(this)的使用说明

  • 2011年03月14日 14:58
  • 17KB
  • 下载

LO_Flaming_Cliffs_2_EN算号器

  • 2017年12月03日 21:01
  • 1.02MB
  • 下载

WINXP下无法使用CAPS LOCK键关闭Caps Lock指示灯

  • 2012年03月20日 09:44
  • 224B
  • 下载

文件加密 源码 file lock

  • 2011年03月22日 13:02
  • 88KB
  • 下载

c#lock 演示代码

  • 2012年12月09日 02:42
  • 38KB
  • 下载

将caps lockt转换成enter同时将Scroll lock转换成caps lock

  • 2012年03月18日 11:23
  • 200B
  • 下载
收藏助手
不良信息举报
您举报文章:Lock Convoys
举报原因:
原因补充:

(最多只允许输入30个字)