• Delphi 线程安全单例


    在C++中写了一个多线程环境下写日志的插件,考虑到以前写Delphi代码时对文件的操作类封装时老是欠缺线程安全方面的考虑,所以总结了一下,写了一个线程安全的单例。可能有欠缺之处请各位朋友多多指教。

    首先自己封了一个多线程的临界操作类,用来管理多线程的临界区,方法很简单只是单独对WINDOWS API的封装,实现单元如下:

    (*******************************************************************
    *@file: CriticalSectionU.pas
    *@desc: 多线程操作时,对临界区的封装
    *@author: daihw
    *@date: 2009-03-03
    *******************************************************************)

    unit CriticalSectionU;

    interface
    uses Windows,Classes,CommCtrl,Dialogs;

    type
        TMCriticalSection=class(TObject)
       protected
         FCriticalSection:TRTLCriticalSection;
       public
         constructor create;
         destructor destory;
         function Init():TRTLCriticalSection; 
         function lock():Boolean; 
         function unlock():Boolean;
         function Trim():Boolean;
       end;
       TMAutoCriticalSection=class(TMCriticalSection)
       public
         constructor Create;
         destructor Destory;
       end;
       TMsafeDeleteCriticalSection=class(TMCriticalSection)
       private
         m_bInitialized:Boolean; 
       public
         constructor Create;
         destructor Destory ;
         function Init():TRTLCriticalSection;
         function lock():Boolean;
         function unlock():Boolean;
         function Trim():Boolean;
       end;

    implementation

    { TMCriticalSection }

    constructor TMCriticalSection.create;
    begin
    InitializeCriticalSection(FCriticalSection);
    end;

    destructor TMCriticalSection.destory;
    begin
       DeleteCriticalSection(FcriticalSection);
    end;

    function TMCriticalSection.Init: TRTLCriticalSection;
    begin
         RESULT := FCriticalSection;
    end;

    function TMCriticalSection.lock: Boolean;
    begin
    EnterCriticalSection(FCriticalSection);
    Result:=true;
    end;

    function TMCriticalSection.Trim: Boolean;
    begin
    DeleteCriticalSection(FcriticalSection);
    Result:=true;
    end;

    function TMCriticalSection.unlock: Boolean;
    begin
    LeaveCriticalSection(FcriticalSection);
    Result:=true; 
    end;

    { TMAutoCriticalSection }

    constructor TMAutoCriticalSection.Create;
    begin
    inherited Create;
    end;

    destructor TMAutoCriticalSection.Destory;
    begin
    inherited Destory;
    end;

    { TMsafeDeleteCriticalSection }

    constructor TMsafeDeleteCriticalSection.Create;
    begin
    inherited Create;
    m_bInitialized:=True;
    end;

    destructor TMsafeDeleteCriticalSection.Destory;
    begin
    m_bInitialized:=False;
    inherited Destory; 
    end;

    function TMsafeDeleteCriticalSection.Init: TRTLCriticalSection;
    begin
    if (m_bInitialized) then
    Result:=Init; 
    end;

    function TMsafeDeleteCriticalSection.lock: Boolean;
    begin
    if (m_bInitialized) then
        Result:= inherited lock
    else
        Result:=False;
    end;

    function TMsafeDeleteCriticalSection.Trim: Boolean;
    begin
    if (m_bInitialized) then
         Result:= inherited Trim
    else
         Result:=False;
    end;

    function TMsafeDeleteCriticalSection.unlock: Boolean;
    begin
    if (m_bInitialized) then
         Result:= inherited unlock
    else
         Result:=true; 
    end;

    end.

    做好临界处理后,开始实现线程安全的单例对象,实现代码如下:

    (*******************************************************************
    *@file: singletonU.pas
    *@desc: 线程安全的单例,通过引用计数维护对象生命周期.
    *@author: daihw
    *@date: 2009-03-03
    *******************************************************************)
    unit SingletonU;

    interface
    uses Classes, SysUtils, CommCtrl, Dialogs, Windows, CriticalSectionU;
    type
    TDSingletonCreator = class(TObject)
    private
        FMsg: string;
    public
        property Msg: string read FMsg write FMsg;
        class function Instance(): TDSingletonCreator;
        class function Release(): Integer;
        class function NewInstance: TObject; override;
        procedure FreeInstance; override;
    end;
    implementation
    var
    _sc: TMsafeDeleteCriticalSection = nil;
    _self: TDSingletonCreator = nil;
    _refCount: LongInt = 0;

    { TDSingleton }

    procedure TDSingletonCreator.FreeInstance;
    begin
    inherited;
    _sc := nil;
    _self := nil;
    end;

    class function TDSingletonCreator.Instance: TDSingletonCreator;
    begin
    if not Assigned(_sc) then
    begin
        _sc := TMsafeDeleteCriticalSection.create();
    end;
    _sc.lock();
    if not Assigned(_self) then
        _self := TDSingletonCreator.create;
    _sc.unlock();
    Inc(_refCount);
    Result := _self;
    end;

    class function TDSingletonCreator.NewInstance: TObject;
    begin
    if not Assigned(_sc) then
    begin
        _sc := TMsafeDeleteCriticalSection.create();
    end;
    _sc.lock();
    if not Assigned(_self) then
        _self := TDSingletonCreator(inherited NewInstance);
    _sc.unlock();
    Inc(_refCount);
    Result := _self;
    end;

    class function TDSingletonCreator.Release: Integer;
    begin
    if Assigned(_sc) then
    begin
        _sc.lock();
        if (_refCount = 0) then
          Result := 0;
        Dec(_refCount);
        if (_refCount = 0) then
          if Assigned(_self) then
            FreeAndNil(_self);
        _sc.unlock();
        if (_refCount = 0) then
          FreeAndNil(_sc);
        Result := _refCount;
    end
    else
        Result := 0;
    end;

    end.

    测试代码如下:

    unit TestU;

    interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;

    type
    TForm1 = class(TForm)
        btn1: TButton;
        btn2: TButton;
        procedure btn1Click(Sender: TObject);
        procedure btn2Click(Sender: TObject);
    private
        { Private declarations }
    public
        { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    uses
    SingletonU;

    {$R *.dfm}

    procedure TForm1.btn1Click(Sender: TObject);
    var
    singleton:TDSingletonCreator;
    begin
    singleton:=TDSingletonCreator.Instance;
    singleton.Msg:='121212';
    TDSingletonCreator.Release;
    end;

    procedure TForm1.btn2Click(Sender: TObject);
    var
    singleton:TDSingletonCreator;
    begin
    singleton:=TDSingletonCreator.Create;
    ShowMessage(singleton.msg);
    singleton.Free;  
    end;

    end.

    总结:这片文章写出来可能对多线程环境下文件操作,有点帮助,比如:日志文件的读写操作。
  • 相关阅读:
    getContentResolver()内容解析者查询联系人、插入联系人
    ContentProvider备份短信,以xml文件存储
    ContentProvider详解
    bindService初步了解
    Service之来电监听(失败的案例)
    Android帧动画
    AlertDialog之常见对话框(单选对话框、多选对话框、进度条对话框)
    BroadcastReceiver之(手动代码注册广播)屏幕锁屏、解锁监听、开机自启
    BroadcastReceiver之有序广播
    [FJOI2015]火星商店问题
  • 原文地址:https://www.cnblogs.com/jxgxy/p/2085138.html
Copyright © 2020-2023  润新知