zoukankan      html  css  js  c++  java
  • 混合线程同步构造

      定义:通过合并用户模式和内核模式的构造来构建的,称为混合线程同步构造(hybrid thread synchronization construct).在没有线程竞争的时候,混合构造提供了基于用户模式构造所具有的性能上的优势。在有多个线程同时竞争一个构造的时候,混合构造还使用基于内核模式的构造来提供不“自旋”的优势。
      由于在大多数应用程序中,线程都很少同时竞争一个构造,所以性能上的增强可以使你的应用程序表现得更出色。

      一个简单的混合锁:

      

    internal sealed class SimpleHybridLock : IDisposable{
      // Int32由基元用户模式构造(Interlocked的方法)使用
     private Int32 m_waiters=0;
     // AutoResetEvent是基元内核模式构造
     private AutoResetEvent m_waitLock = new AutoResetEvent(false);
     public void Enter(){
            if(Interlocked.Increment(ref m_waiters)==1)   
            {
                 return; //此时锁可自由使用,无竞争,直接返回
            } 
            //另一个线程正在等待。这代表一个竞争,因此阻塞这个线程
            m_waitLock.WaitOne();//这里产生较大的性能影响
            //WaitOne返回后,这个线程现在拥有了锁    
        }
      public void Leave(){
           if(Interlocked.Increment(ref m_waiters)==0)
           {
                return;//不存在需要唤醒的线程了,直接返回
            }
            //有其它线程正在阻塞,唤醒其中一个
            m_waitLock.Set();//这里产生较大的性能影响
        }
       public void Dispose(){
           m_waitLock.Dispose();
        }
    }        

     SimpleHybridLock包含两个字段:一个 Int32,它将通过基元用户模式的构造来操作;以及一个AutoResetEvent,它是一个基于内核模式的构造.为了获得出色的性能,锁尽量使用Int32,尽量避免使用AutoResetEvent.只是构造一个SimpleHybridLock对象,就会导致AutoResetEvent的创建;相较于Int32字段所产生的开销,这会使性能造成较大的损失。

      SimpleHybridLock解释:

        调用Enter的第一个线程造成Interlocked.Increment在m_waiters字段上加1,使它的值变成1.这个线程发现以前有零个线程正在等待这个锁,所以线程从它的Enter调用中返回。值得欣赏的是,线程获得锁的速度是非常快的。现在如果另一个线程介入并调用Enter,这个线程将 m_waiters递增到2,发现锁在另一个线程那里。所以,这个线程会使用AutoResetEvent对象来调用WaitOne,从而阻塞自身。调用WaitOne造成线程的代码转换成内核模式的代码,这会对性能产生巨大影响。然而,线程现在会阻塞,不会因为在CPU上“自旋”而浪费CPU的时间。

        调用Leave方法时,会调用Interlocked.Decrement从m_waiters字段减1.如果m_waiters现在是0,表明没有其他线程在对Enter的调用中发生阻塞,调用Leave的线程可以直接返回。同样地,想象一下这有多快:离开一个锁意味着一个线程从一个Int32中减1,执行快速的if测试,然后返回!另一方面,如果调用Leave的线程发现m_waiters不为1,线程就知道现在存在一个竞争,另外至少有一个线程在内核中阻塞。这个线程必须唤醒一个(而且只能是一个)阻塞的线程。唤醒线程是通过在AutoResetEvent上调用Set来实现的。这会造成性能上的损失,因为线程必须转换成内核模式的代码,然后又转回来。但是,只有在发生竞争是,才会发生这种转换。当然,AutoResetEvent确保只有一个阻塞的线程被唤醒;在AutoResetEvent上阻塞的其他所有线程会继续阻塞,直到新的、解除了阻塞的线程最终调用Leave。

  • 相关阅读:
    angular 复选框回选
    $parse
    AngularJS 指令的 Scope (作用域)
    文献解读 (1)
    献给初学者:常用的细胞凋亡检测方法
    KofamKOALA
    Dfam.h5.gz下载
    Augustus-3.3.3安装
    bamtools 2.5.1安装
    R语言从原点开始作图
  • 原文地址:https://www.cnblogs.com/huaan011/p/3582549.html
Copyright © 2011-2022 走看看