选择性临界区 - 有条件

发布于 2024-11-01 05:40:29 字数 494 浏览 2 评论 0原文

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

TMyThread 的 1 个实例可以有一个“Member”数据库表,而另一个实例可以有“Staff”数据库表,但是可能存在使用同一个表打开两个线程的情况。

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

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

我们有8个表,因此会变得混乱 有什么办法可以做到

TCricalSection(fMemberTable).Enter; 或者某种易于“扩展”和使用的方法来做到这一点?

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

I got a thread which takes a db table as a paramater, I got an issue where I can't write to that db table at the same time.

1 instance of TMyThread can have a db table of 'Member' while another could have 'Staff' however there can be cases of two threads open with the same table.

Thus, I need to wrap the code in a critical section (or similar) but I don't want some dirty thing like several crical sections like (fMemberTable, fStaffTable)...

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

We have 8 tables so that would get messy
Is there some way to do

TCricalSection(fMemberTable).Enter;
Or some way to do this which is easy to 'scale' and use?

One critical section around the function doesn't make sense, as I don't want to hold back other tables....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉城凉梦凉人心 2024-11-08 05:40:29

你可以这样做:

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

请注意这是一个自旋锁,而不是真正的关键部分。如果您不会发生很多冲突,那么非常实用,但如果线程定期相互阻塞,您可能需要回退到临界区。根据定义,自旋锁是忙等待锁。

但我不确定 Delphi 的哪个版本引入了此功能,并且您没有特定于版本的标签。

You can do:

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

Please note this is a SPIN LOCK, not a true critical section. Very practical if you're not going to have a lot of collisions, but if threads block each other regularly, you might want to fall back to the critical section. The spin lock is, by definition, a busy-wait lock.

but I'm not sure what version of Delphi introduced this and you don't have version-specific tags.

岁月流歌 2024-11-08 05:40:29

您可以使用关键部分列表,例如,本单元中定义的我的类:

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.

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

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

您可以编写像这样的代码:

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

享受。

You can use a Critical Section list, for example, My class defined in this unit:

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.

The class basically define a List of critical sections, accesible by "name". The first time you ask for a Critical section of a particular name that critical section is automatically created for you. You must access a single instance of this class, use the provided CSList function.

All critical sections are destroyed when the instance of the list is destroyed, for instance, the "default" instance is destroyed upon application end.

You can write code like this example:

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

Enjoy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文