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.
总结:这片文章写出来可能对多线程环境下文件操作,有点帮助,比如:日志文件的读写操作。