gpt4 book ai didi

multithreading - 如何在多线程应用程序中保护和访问嵌套对象

转载 作者:行者123 更新时间:2023-12-03 18:40:41 28 4
gpt4 key购买 nike

我有一个带有嵌套对象的对象。对象组织的简单图为:

TMainObj
-TState
-TDescriptor
-List<TSubObj>
--TSubObj_n
---TSubObjState
---TSubObjDesc
---TSubObjData

type TState = class
end;

type TDesc = class
end;

type TSubObjState = class
end;

type TSubObjDesc = class
end;

type TSubObjData = class
end;

type TSubObj = class
FSubObjState: TSubObjState;
FSubObjDesc: TSubObjDesc;
FSubObjData: TSubObjData;
end;

type TListSubObj = class (TList<TSubObj>)
end;

type TMainObj = class
FState: TState;
FDesc: TDesc;
FList: TList<TSubObj>
end;

我有多线程应用程序,必须启用对对象及其属性的访问(本示例代码中未包含)。有些线程共享一些相同的对象,有些却没有,但是在我需要保护数据之前,它们仍然可以与主线程共享某些属性。我正在使用关键部分/互斥来保护数据。但是,我不知道如何在此方案中组织锁定机制以从中获得最大的 yield 。

我最初的想法是在TMainObj上实现锁定/解锁,每当任何线程需要访问任何属性或子对象时,它都会锁定完整的TMainObj,而所有其他线程将需要等待,直到TMainObj解锁为止。因此,我认为这不是一个好主意。一些线程不需要访问TMainObj的属性,而只需访问它的子对象,例如TState。我认为没有必要锁定整个TMainObj,而只需锁定TState还是我错过了什么?

如果我需要访问TMainObj上的属性,则可以执行以下操作:
TMainObj.Lock
try
TMainObj.Name := 'Just name!';
TManiObj.Id := 1;
finally
TMainObj.Unlock;
end;

其他所有线程都必须等待获取访问权限。

但是,当我需要访问子类TDescriptor时该怎么办?我可以这样:
TMainObj.Lock
try
TMainObj.Descriptor.DataLen := 1024;
TManiObj.Descriptor.Count := 10;
finally
TMainObj.Unlock;
end;

并且完整的TMainObj将被锁定。并且所有其他线程都需要等待,即使它们对更改TMainObj的属性不感兴趣。

或仅锁定子对象描述符的方式:
Thread1:
TMainObj.Descriptor.Lock
try
TMainObj.Descriptor.DataLen := 1024;
TManiObj.Descriptor.Count := 10;
finally
TMainObj.Descriptor.Unlock;
end;

同时,其他一些线程仍然可以访问TMainObj属性并对其进行更改,对吗?
Thread2: 
TMainObj.Lock;
try
TMainObj.Name := 'New name!';
finally
TMainObj.Unlock;
end;

这是显示每个线程如何以及什么访问的图像。 Threads accessing one object with subobjects

令人担忧的问题之一是僵局。在下一种情况下,我想展示不同的线程如何访问MainObj的不同“部分”。

主线程:
MainObj.Lock;
try
MainObj.Name = 'Different name!'
MainObj.Id = 2;
finally
MainObj.Unlock;
end;

同时thread1正在这样做:
MainObj.Descriptor.Lock;
try
MainObj.Descriptor.DataLen = 1024;
MainObj.Descriptor.Count = 1;
finally
MainObj.Descriptor.Unlock;
end;

因此,两者都共享MainObj,但每个对象都在更改自己的对象部分。这种锁定方法合适吗?

我希望我尽可能清楚地解释我的问题。我的问题是如何保护不同线程对此类对象结构的访问?我是否必须使用自己的锁定/解锁对方法(和关键部分)来保护每个子对象?

最佳答案

您可以为此使用TMonitor而不向对象添加任何内容。在这种情况下,您的代码将如下所示:

TMonitor.Enter(MainObj.Descriptor);
try
MainObj.Descriptor.DataLen := 1024;
MainObj.Descriptor.Count := 10;
finally
TMonitor.Exit(MainObj.Descriptor);
end;

如果所有尝试访问描述符的线程(和主线程)都执行相同的操作,则它们将锁定以等待下一个线程完成。

您将需要提防僵局,但是从您所说的开始就不应该成为问题。如果您执行以下操作,则会发生死锁:
Main Thread
Lock MainObj
Lock MainObj.Descriptor (waits for thread 1)

如果线程1出现并执行此操作:
Thread 1
Lock MainObj.Descriptor
Lock MainObj (waits for main thread)

关于multithreading - 如何在多线程应用程序中保护和访问嵌套对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33154902/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com