zoukankan      html  css  js  c++  java
  • Delphi 在多线程中会应用到的读写锁-“多读一写”同步器-TMultiReadExclusiveWriteSynchronizer

    使用Delphi很多年了,但对VCL的精华还是了解甚少,今天在看国外一个使用Delphi开发的软件加密打包工具enigmavb(Enigma Virtual Box)时,发现国外的技术牛人确实有很多过人之处,该工具直接Hook NTDLL的函数,实现将需要保护的软件和其运行所需文件(DLL/OCX/TXT/INI/DOC)和注册表全部打包到单一的EXE程序,运行时通过HOOK ZwXXXFile、ZwXXXKey和其他Process、Section等相关函数,在EXE进程内部虚拟出一个运行环境,实现类似SandBox的功能。

    在研究期间发现其中使用了一个多线程同步访问对象的类:TMultiReadExclusiveWriteSynchronizer

    功能: 

         当进程中有共享对象需要被多个线程读写访问时,通常做法是使用CriticalSection进行处理,但在某些需要细致优化的程序开发中,会再次细分这些需要被读写的共享对象,可分为下面2类:

         1)经常被读,偶尔被写

         2)经常被读,也经常被写

    对于共享对象,当其数据在内存中没发生变化时,不管多少个线程去读,都不会造成错误,当但有线程在读时,这时候又有其他线程在写,那将会出现读出来的对象可能是有部分被写了,最终读出来的数据相当于不完整或损坏的,因此会发生错误。 所以当共享对象被写时,才需要对其进行保护,当没有线程在写时,是不需要保护的。

          基于上面的特点:

         第一类共享对象,使用CriticalSection明显会降低读的效率,这种情况下,使用TMultiReadExclusiveWriteSynchronizer进行保护则可提高访问效率。

         第二类共享对象,当然也只有选择CriticalSection或者SpinLock了,当然也可以根据实际情况自主实现一些高效的的保护锁。

    TMultiReadExclusiveWriteSynchronizer在VCL中经过复杂的封装后,只需要关心下面这几个方法即可

    procedure BeginRead;  
    procedure EndRead;
    function BeginWrite: Boolean;
    procedure EndWrite;

    Windows 在Vista后提供了 SRWLock, 据说效率比TMultiReadExclusiveWriteSynchronizer高10倍以上,linux下的rwlock实现有官方的和民间的,多种多样,效率不等。

    但是就应用场景而言,TMultiReadExclusiveWriteSynchronizer所牺牲的效率是为了更方便快捷的开发,可以完全替换CriticalSection,没有递归调用的限制。

    而SRWLock和rwlock由于自身无法递归调用的缺点,导致开发中需要非常严谨的编写逻辑,相对来说不是那么容易使用,甚至非常容易出现死锁,超高CPU占用等BUG。

  • 相关阅读:
    [转]Dokuwiki使用感受
    [转]认识与入门Markdown
    [转]2015深度学习回顾:ConvNet、Caffe、Torch及其他
    [转]Dokuwiki插件与主题推荐
    [转]okuwiki布署小记
    PHP环境配置
    keydown和keypress
    JavaScript优化参考
    IE兼容性标签和条件注释
    nodejs 简单http 文件上传demo
  • 原文地址:https://www.cnblogs.com/caibirdy1985/p/4766574.html
Copyright © 2011-2022 走看看