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.

总结:这片文章写出来可能对多线程环境下文件操作,有点帮助,比如:日志文件的读写操作。
原文地址:https://www.cnblogs.com/jxgxy/p/2085138.html