[セットトップ]DELPHI高性能大容量SOCKET同時(5):ロックとオブジェクト分離
5612 ワード
ロックがオブジェクトと一緒にカプセル化される危険
マルチスレッド作成では、ほとんどの符号化スタイルは、ロックとアクセスするオブジェクトを同じオブジェクトにカプセル化するのが好きで、オブジェクトを解放するときもロックを解放します.これにより、デッドロックが発生します.テスト例を書いて、ロックを作成して、ロックをロックして、それからスレッドを作成して、ずっとロックが戻ってくるのを待っていて、それからロックを解放して、この時スレッドはデッドロックして、コードは以下の通りです.
インタフェースの定義:
ロックとオブジェクトの分離
上記の基礎があれば、ロックとオブジェクトを分離する必要があります.IOCPDemoSvrの例コードでは、TSocketHandleは構造体でロックとオブジェクトを管理しています.ロックは作成後、TSocketHandleが解放されてから解放されます.主なコードはTSocketHandlesクラスで、定義ユニットです.
V 1版ダウンロードアドレス:http://download.csdn.net/detail/sqldebug_fan/4510076資源10分が必要で、安定性の問題があり、安定性を研究するために使用することができる.V 2版ダウンロードアドレス:http://download.csdn.net/detail/sqldebug_fan/5560185資源分を必要とせず、安定性の問題を解決し、性能を高めた.免責声明:このコードはIOCPプログラミングを実証するために使用され、学習と研究にのみ使用され、ビジネス用途には使用されません.レベルが限られていて、間違いは避けられないので、指摘と指導を歓迎します.メールアドレス:[email protected]
マルチスレッド作成では、ほとんどの符号化スタイルは、ロックとアクセスするオブジェクトを同じオブジェクトにカプセル化するのが好きで、オブジェクトを解放するときもロックを解放します.これにより、デッドロックが発生します.テスト例を書いて、ロックを作成して、ロックをロックして、それからスレッドを作成して、ずっとロックが戻ってくるのを待っていて、それからロックを解放して、この時スレッドはデッドロックして、コードは以下の通りです.
インタフェースの定義:
type
TLockObject = class;
TLockTestThread = class;
TForm1 = class(TForm)
btn1: TButton;
mmoLockThreadTest: TMemo;
procedure btn1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
FLockTestThread: TLockTestThread;
FLockObject: TLockObject;
public
{ Public declarations }
end;
TLockTestThread = class(TThread)
private
FLockObject: TLockObject;
public
procedure Execute; override;
procedure AddLockLog;
property LockObject: TLockObject read FLockObject write FLockObject;
end;
TLockObject = class(TObject)
private
FLock: TCriticalSection;
public
constructor Create; virtual;
destructor Destroy; override;
procedure Lock;
procedure UnLock;
end;
var
Form1: TForm1;
Form 1の作成時にロックを作成し、ロックをロックし、スレッド待機ロックの戻りを作成します.procedure TForm1.FormCreate(Sender: TObject);
begin
FLockObject := TLockObject.Create;
FLockObject.Lock;
FLockTestThread := TLockTestThread.Create(True);
FLockTestThread.LockObject := FLockObject;
FLockTestThread.FreeOnTerminate := True;
FLockTestThread.Resume;
end;
スレッドの実行方法は、ロックが戻るのを待ってログを書きます.フォームの作成時にロックがロックされているため、スレッドは待機します.procedure TLockTestThread.AddLockLog;
begin
Form1.mmoLockThreadTest.Lines.Add('Lock')
end;
procedure TLockTestThread.Execute;
begin
inherited;
while not Terminated do
begin
FLockObject.Lock;
Synchronize(AddLockLog);
end;
end;
この時点でスレッドはずっと待っています.FLockObjectを解放すると、スレッドもずっと待っていて、デッドロックになります.procedure TForm1.btn1Click(Sender: TObject);
begin
FLockObject.Lock;
FLockObject.Free;
FLockObject := nil;
end;
ロックとオブジェクトの分離
上記の基礎があれば、ロックとオブジェクトを分離する必要があります.IOCPDemoSvrの例コードでは、TSocketHandleは構造体でロックとオブジェクトを管理しています.ロックは作成後、TSocketHandleが解放されてから解放されます.主なコードはTSocketHandlesクラスで、定義ユニットです.
{* Socket *}
TSocketHandles = class(TObject)
private
{* *}
FList: TList;
{* *}
FIdleList: TList;
{* *}
FLock: TCriticalSection;
{* *}
function GetItems(const AIndex: Integer): PClientSocket;
{* *}
function GetCount: Integer;
{* *}
procedure Clear;
public
constructor Create; virtual;
destructor Destroy; override;
{* *}
procedure Lock;
{* *}
procedure UnLock;
{* *}
function Add(ASocketHandle: TSocketHandle): Integer;
{* *}
procedure Delete(const AIndex: Integer); overload;
procedure Delete(ASocketHandle: TSocketHandle); overload;
property Items[const AIndex: Integer]: PClientSocket read GetItems; default;
property Count: Integer read GetCount;
end;
実装ユニット:{ TSocketHandles }
constructor TSocketHandles.Create;
begin
FList := TList.Create;
FIdleList := TList.Create;
FLock := TCriticalSection.Create;
end;
destructor TSocketHandles.Destroy;
begin
Clear;
FList.Free;
FIdleList.Free;
FLock.Free;
inherited;
end;
function TSocketHandles.GetItems(const AIndex: Integer): PClientSocket;
begin
Result := FList[AIndex];
end;
function TSocketHandles.GetCount: Integer;
begin
Result := FList.Count;
end;
procedure TSocketHandles.Clear;
var
i: Integer;
ClientSocket: PClientSocket;
begin
for i := 0 to Count - 1 do
begin
ClientSocket := Items[i];
ClientSocket.Lock.Free;
ClientSocket.SocketHandle.Free;
Dispose(ClientSocket);
end;
FList.Clear;
for i := 0 to FIdleList.Count - 1 do
begin
ClientSocket := FIdleList[i];
ClientSocket.Lock.Free; //
Dispose(ClientSocket);
end;
FIdleList.Clear;
end;
procedure TSocketHandles.Lock;
begin
FLock.Enter;
end;
procedure TSocketHandles.UnLock;
begin
FLock.Leave;
end;
function TSocketHandles.Add(ASocketHandle: TSocketHandle): Integer;
var
ClientSocket: PClientSocket;
begin
if FIdleList.Count > 0 then //
begin
ClientSocket := FIdleList[0];
FIdleList.Delete(0);
end
else //
begin
New(ClientSocket);
ClientSocket.Lock := TCriticalSection.Create;
end;
ClientSocket.SocketHandle := ASocketHandle;
ASocketHandle.FLock := ClientSocket.Lock;
Result := FList.Add(ClientSocket);
end;
procedure TSocketHandles.Delete(const AIndex: Integer);
var
ClientSocket: PClientSocket;
begin
ClientSocket := FList[AIndex];
ClientSocket.Lock.Enter;
try
ClientSocket.SocketHandle.Free;
ClientSocket.SocketHandle := nil;
finally
ClientSocket.Lock.Leave;
end;
FList.Delete(AIndex);
if FIdleList.Count > MAX_IDLELOCK then // ,
Dispose(ClientSocket)
else
FIdleList.Add(ClientSocket);
end;
procedure TSocketHandles.Delete(ASocketHandle: TSocketHandle);
var
i, iIndex: Integer;
begin
iIndex := -1;
for i := 0 to Count - 1 do
begin
if Items[i].SocketHandle = ASocketHandle then
begin
iIndex := i;
Break;
end;
end;
if iIndex <> -1 then
begin
Delete(iIndex);
end;
end;
V 1版ダウンロードアドレス:http://download.csdn.net/detail/sqldebug_fan/4510076資源10分が必要で、安定性の問題があり、安定性を研究するために使用することができる.V 2版ダウンロードアドレス:http://download.csdn.net/detail/sqldebug_fan/5560185資源分を必要とせず、安定性の問題を解決し、性能を高めた.免責声明:このコードはIOCPプログラミングを実証するために使用され、学習と研究にのみ使用され、ビジネス用途には使用されません.レベルが限られていて、間違いは避けられないので、指摘と指導を歓迎します.メールアドレス:[email protected]