我有一個嵌套對象的對象。對象機構組織的簡圖將是:如何保護和訪問多線程應用程序中的嵌套對象
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版本添加一個標籤 - 可用的線程代碼有所不同。 –