.net 基元用户模式和内核模式构造

基元线程同步构造。所谓基元,我的意思是指可以在代码中使用的最简单的构造。由两种基元构造:用户模式(user-mode)和内核模式(kenel-mode).应该尽量使用基元用户模式构造,它们的速度要显著快于内核模式的构造。这是因为它们使用了特殊CPU指令来协调线程。这意味着协调是在硬件中发生的(所以才这么快)。但是,这同时意味着Microsoft Windows操作系统永远检测不到一个线程在一个基元用户模式中构造上的阻塞了。由于在用户模式的基元构造上阻塞的一个线程池线程永远不认为已经阻塞,所以线程池不会创建一个新线程来替换这种临时阻塞的线程。除此以外,这些CPU指令只是阻塞线程极短的一段时间。

所有这一切听起来真不错,是吧?确实不错,这是我建议尽量使用这些构造的原因。但是,它们也有一个缺点:只有windows操作系统内核才能停止一个线程的运行(以避免浪费CPU时间)。在用户模式中运行的线程可能被系统抢占(preempted), 但线程会以最快的速度再次调度。所以想要取得一个资源但又暂时取不到一个线程会一直在用户模式中运行。这可能浪费大量CPU时间,而这些CPU时间本来可以用来执行其他更有用的工作。即便没有其他更有用的工作,更好的做法也是让CPU空闲。

这使我们将眼光投向了基元内核模式构造。内核模式的构造是由Windows操作系统自身提供的。所以它们要求你在应用程序的线程中调用在操作系统内核实现的函数。将线程从用户模式切换为内核模式(或相反)会招致巨大的性能损失,这正是为什么应该避免使用内核模式构造的原因。然后,它们有一个重要的有点:一个线程使用一个内核模式的构造获取一个由其他线程拥有的资源时,Windows会阻塞线程,使它不再浪费CPU时间。然后当资源变得可用时,windows会恢复线程,允许它访问资源。

对于在一个构造上等待的线程,如果拥有这个构造的线程一直不释放它,前者就可能一直阻塞。如果这是一个用户模式的构造,线程将一直在一个cpu上运行,我们称之为“活锁”(livelock)。如果这是一个内核模式的构造,线程将一直阻塞,我们称之为“死锁”(deadlock)。两种情况都是不好的情况。但在两者之间,死锁总是优于活锁,因为活锁即浪费CPU时间,又浪费内存(线程栈等等),而死锁只浪费内存。

理想中的构造应兼具两者的长处,也就是说,在没有竞争的情况下,这个构造应该快且不会阻塞(就像用户模式的构造)。但是,如果存在对构造的竞争,我希望它被操作系统内核阻塞。像这样的构造是确实存在的:我将它们称为混合构造(hybrid construct)。应用程序使用混合构造是一种很常见的现象,因为在大多数应用程序中,很少会有两个或多个线程同时访问相同的数据。混合构造使你的应用程序在大多数时间都快速运行,偶尔运行得比较慢以阻塞线程。但在这时运行的慢一些是不要紧得,因为你的线程反而都要阻塞。

CLR的许多线程同步构造只是围绕Win32的 “线程同步构造”的一些面向对象的类包装器而已。毕竟,CLR线程就是Windows线程,这意味着要由Windows调度和控制线程的同步。Windows线程同步构造自1992年开始便存在了,人们已经就这个主题撰写了大量的内容。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值