我有一个嵌套对象的对象。对象机构组织的简图将是:如何保护和访问多线程应用程序中的嵌套对象
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;
我的多线程应用程序,我必须能够访问对象及其属性(其不包括在本实施例中的代码)。有些线程共享相同的对象,但仍然可以与主线程共享某些属性,因此我需要保护数据。我正在用关键部分/互斥体保护数据。不过,我不知道如何在这个方案中组织锁定机制以充分利用它。
我最初的想法是在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;
其中一个问题是死锁情况。在下一个例子中,我想展示不同的线程如何访问MainObj的不同“部分”。
MainThread:
MainObj.Lock;
try
MainObj.Name = 'Different name!'
MainObj.Id = 2;
finally
MainObj.Unlock;
end;
同时线程1是这样做的:
MainObj.Descriptor.Lock;
try
MainObj.Descriptor.DataLen = 1024;
MainObj.Descriptor.Count = 1;
finally
MainObj.Descriptor.Unlock;
end;
所以两者的共享MainObj但每次改变对象的自己的一部分。这种锁定方式是否合适?
我希望我尽可能清楚地解释我的问题。我的问题是如何保护从不同线程访问这种对象结构?我是否必须使用自己的锁定/解锁对方法(和关键部分)来保护每个子对象?
MainThread正在与TMainObject和它的属性和子对象(TSTATE,TDescription)。我有其他线程。一个只使用TState,另一个只使用TDescription。所以每个线程都与mainthread共享一些东西。因此,当主线程仅更改MainObject上的属性时,锁必须仅锁定那些属性,而其他线程仍可以更改TState或TDescriptor对象。我的问题是,如果这是确定的,我只锁定对象的某些部分,或者我应该锁定完整的对象? – Nix
很难建议你没有完整的图片,在我看来 –
请为你的Delphi版本添加一个标签 - 可用的线程代码有所不同。 –