选择性临界区 - 有条件的

时间:2011-04-14 09:07:56

标签: multithreading delphi thread-safety critical-section

我有一个线程,它将db表作为参数,我遇到了一个问题,我无法同时写入该数据库表。

TMyThread的1个实例可以有一个'Member'的db表,而另一个可以有'Staff'但是可能有两个线程打开同一个表的情况。

因此,我需要将代码包装在一个关键部分(或类似的部分)中,但我不想要像(fMemberTable,fStaffTable)这样的几个部分那些脏东西...

begin
    if fDBTable = 'Member' then
        fMemberTable.Enter
    else if fDbTable = 'Staff' then
    ....

我们有8张桌子,所以会变得混乱 有办法吗

TCricalSection(fMemberTable)。进入; 或者某种方式做到这一点很容易“缩放”和使用?

围绕该功能的一个关键部分没有意义,因为我不想阻止其他表....

2 个答案:

答案 0 :(得分:2)

你可以这样做:

TMonitor.Enter(fMemberTable);
try
  // Do your stuff
finally TMonitor.Exit(fMemberTable);
end;

请注意这是一个旋转锁,而不是真正的关键部分。如果你不会发生很多碰撞,那么非常实用,但是如果线程经常相互阻塞,你可能会想要回到关键部分。根据定义,自旋锁是一个忙等待锁。

但是我不确定Delphi的哪个版本引入了这个版本,而且你没有版本特定的标签。

答案 1 :(得分:0)

您可以使用Critical Section列表,例如,在此单元中定义的My class:

interface
uses Classes, SyncObjs;

type
  { TCriticalSectionList by jachguate }
  { http://jachguate.wordpress.com }
  TCriticalSectionList = class
  private
    FCSList: TThreadList;
    FNameList: TStringList;
    function GetByName(AName: string): TCriticalSection;
  public
    constructor Create();
    destructor Destroy(); override;
    property ByName[AName: string]: TCriticalSection read GetByName; default;
  end;

  function CSList: TCriticalSectionList;

implementation
uses SysUtils;

{ TCriticalSectionList }

constructor TCriticalSectionList.Create;
begin
  inherited;
  FCSList := TThreadList.Create;
  FNameList := TStringList.Create;
end;

destructor TCriticalSectionList.Destroy;
var
  I: Integer;
  AList: TList;
begin
  AList := FCSList.LockList;
  for I := AList.Count - 1 downto 0 do
    TCriticalSection(AList[I]).Free;
  FCSList.Free;
  FNameList.Free;
  inherited;
end;


function TCriticalSectionList.GetByName(AName: string): TCriticalSection;
var
  AList: TList;
  AIdx: Integer;
begin
  AList := FCSList.LockList;
  try
    AName := UpperCase(AName);
    AIdx := FNameList.IndexOf(AName);
    if AIdx < 0 then
    begin
      FNameList.Add(AName);
      Result := TCriticalSection.Create;
      AList.Add(Result);
    end
    else
      Result := AList[AIdx];
  finally
    FCSList.UnlockList;
  end;
end;

var
  _CSList: TCriticalSectionList;

function CSList: TCriticalSectionList;
begin
  if not Assigned(_CSList) then
    _CSList := TCriticalSectionList.Create;
  Result := _CSList;
end;

initialization
  _CSList := nil;
finalization
  _CSList.Free;
end.

该类基本上定义了一个关键部分列表,可通过“name”访问。第一次请求特定名称的“关键”部分时,会自动为您创建关键部分。您必须访问此类的单个实例,使用提供的CSList函数。

当列表实例被销毁时,所有关键部分都被销毁,例如,“default”实例在应用程序结束时被销毁。

您可以编写如下示例的代码:

begin
  CSList[fDBTable].Enter;
  try
    DoStuff;
  finally
    CSList[fDBTable].Leave;
  end;
end;

享受。