• 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。

  • 相关阅读:
    Python-内存管理
    Python如何操作Excel
    336. 文本压缩
    Python-锁
    MVC接收以post形式传输的各种参数
    linux批量替换指定文件夹中所有文件的指定内容
    ES6:string.raw浅析
    node学习笔记
    运行node提示:events.js:160 throw er; // Unhandled 'error' event
    socket.io入门示例参考
  • 原文地址:https://www.cnblogs.com/caibirdy1985/p/4766574.html
Copyright © 2020-2023  润新知