2011-05-08 64 views
3

我有一個多線程的Delphi程序創建了一些類的多個實例,我希望每個類實例都有自己的TMultiReadExclusiveWriteSynchronizer實例,以用於特定屬性的get和set方法。「擁有」TMultiReadExclusiveWriteSynchronizer實例的類實例?

E.g.下面是我在一個類中使用TMultiReadExclusiveWriteSynchronizer其中一個單元的一部分:

interface 

TSGThread=class(TThread) 
private 
    fWaiting:boolean; 
    function getWaiting:boolean; 
    procedure setWaiting(value:boolean); 
public 
    property waiting:boolean read getWaiting write setWaiting; 
end; 

implementation 

var syncWaiting:TMultiReadExclusiveWriteSynchronizer; 

function TSGThread.getWaiting:boolean; 
begin 
    syncWaiting.BeginRead; 
    result:=fWaiting; 
    syncWaiting.EndRead; 
end; 

procedure TSGThread.setWaiting(value:boolean); 
begin 
    syncWaiting.BeginWrite; 
    fWaiting:=value; 
    syncWaiting.EndWrite; 
end; 

initialization 
    syncWaiting:=TMultiReadExclusiveWriteSynchronizer.Create; 
finalization 
    syncWaiting.Free; 
end. 

的問題,這是該單位創建TMultiReadExclusiveWriteSynchronizer的一個實例,然後使用TSGThread的多個實例。
同步器只控制對TSGThread的專用字段的訪問。
線程A可以使用公共屬性修改線程B中的字段,因此需要同步器,但每個線程中應該有一個單獨的同步器,以便線程不必在彼此之間等待他們自己的屬性。

德爾福幫助說「創建一個TMultiReadExclusiveWriteSynchronizer的全局實例」,但它是否絕對必須始終是全球?
如果一個類只保護對自己屬性的訪問,那麼同步是否可以在私有字段中使用TMultiReadExclusiveWriteSynchronizer實例?

+0

看到下面的答案後,我已經用私有字段中的同步器成功測試了我的類。 – 2011-05-08 04:07:13

回答

2

它不是絕對必要的,它是全球性的。它是爲了保持線程安全,每次訪問都需要通過同步器。一種簡單的方法可以使同步器成爲全局變量,但還有其他方法可以處理它。

+0

接受這一個只是因爲它出現在第一個答案,但羅布的答案同樣有用。 – 2011-05-08 04:05:55

4

The help這樣說:

創建一個與您要保護的全局內存關聯TMultiReadExclusiveWriteSynchronizer全局實例。

但是您沒有全球內存。你有線程對象特定的內存,所以爲每個線程對象創建同步對象。您可以根據需要創建多個。爲您希望單獨訪問和保護的每個共享元素創建一個。

3

這有點偏離主題,但在你給出的例子中,同步器幾乎沒用。布爾值不能在線程上下文切換中部分讀取/寫入。

而且,你的榜樣,這樣的代碼

sgThread.Waiting := not sgThread.Waiting; 

可能失敗。

現在,回到主題。 TMultiReadExclusiveWriteSynchronizer的範圍需要與其保護的資源一樣大。既然你想保護一個對象的私有字段,你也可以將TMultiReadExclusiveWriteSynchronizer聲明爲私有字段。 (您正在保護對私人領域的訪問權限,而不是訪問財產)

+0

我使用的是同步器,因爲我最近做了一些Java線程代碼,閱讀過關於Java的「volatile」說明符,得到了這樣的印象:每當單獨的線程可以讀/寫相同的字段時,推薦使用它,德爾福的TMultiReadExclusiveWriteSynchronizer是一個體面的當量。 – 2011-05-09 03:02:41

+0

關於** sgThread.Waiting:= not sgThread.Waiting; **情況,在屬性的set方法被調用之前不會評估右側(完成get方法)嗎? – 2011-05-09 03:05:00

+0

是的,如果調用set方法,將評估右側。問題是另一個線程實際上可以讀取和修改Get和Set之間的值,這會產生不可預知的結果。如果你有2個線程執行上面的行......可以說,每個10個時間。最後你不會總是有相同的結果。 – 2011-05-09 03:43:15