Autor Beitrag
neuling82
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 33



BeitragVerfasst: Mi 06.08.03 09:48 
ich habe zwei units, in einem erzeuge ich ein Threadobjekt, in der anderen habe ich zwei global veriablen. nun möchte ich den Thread diese 2 Variablen schreiben lassen, es kann jedoch sein, dass sie in dieser Zeit von einer Procedure in der "Nicht-Thread_unit" gelesen werden. Dass müsste verhindert werden. Kann ich das mit TCriticalsection tun?
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Mi 06.08.03 10:12 
Hallo!

neuling82 hat folgendes geschrieben:
Kann ich das mit TCriticalsection tun?
Ja!

In deinem Thread Objekt erstellst du eine Instance von TCriticalSection:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
Constructor TMyThread.Create (...);
Begin
  fCriticalSection := TCriticalSection.Create;
End;

Wenn du jetzt schriebend auf die Variablen zugreifen willst baust du die Critiacalsection darum:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
fCriticalSection.Enter;
try
  { Hier der Schreibvorgang }
finally
  fCriticalSection.Leave;
end;

Nicht vergessen die Instance wieder frei zu geben!

Gruß
Tino
neuling82 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 33



BeitragVerfasst: Mi 06.08.03 10:37 
und benötige ich das auch, wenn ich ein Thread objekt habe, welches eine globale Procedure aufruft und etwas in deren Variablen übergibt. nur das Thread objekt ruft die Procedure auf, dafür ist gesorgt. wenn diese Procedure dann die Variablen setzt (die Procedure ist eine Globale in der Unit!!) ist das dann auch nötig, oder nur wenn es eine Procedure im ThreadObjekt wäre??
Tana´Ri
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 230



BeitragVerfasst: Mi 06.08.03 14:30 
sobald mehrere auf den gleichen Speicherbereich zugreifen, d.h. dein thread könnte gerade in der Proc stecken und ne var setzen die dein form gerade lesen will, was wird wird wohl passieren .. klatsch!!

Synchronize ab D6 nicht mehr zu empfehlen (hörensagen)

aber TCriticalSection ist gut !
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
 
procedure Thread.Execute;
 repeat
  with TCriticalSection.Create do  
   try
    Enter;
     YourProc;
    Leave;
   finally
    Free;
   end;
 until (terminated);
end;

so kannste des sogar ohne Instanz mache, für die faule ;)

Moderiert von user profile iconTino: Delphi-Tags hinzugefügt.

_________________
mfg
Tana´Ri
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mi 06.08.03 15:03 
@Tana´Ri:
der Aufruf von Leave gehört auch in den finally-Abschnitt, damit die CriticalSection auch im Falle einer Exception korrekt verlassen wird..!

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Tana´Ri
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 230



BeitragVerfasst: Mi 06.08.03 15:07 
stimmt :oops:

_________________
mfg
Tana´Ri
datensender
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 18

Windows 2000 P / Gentoo
D5 Enterprise
BeitragVerfasst: Do 07.08.03 09:42 
nur mal btw... die Critical Section (CS) muss für alle (beteiligten) Threads sichtbar sein...
das CS-Exemplar wird bei der zu schützenden Resource gebildet und nicht innerhalb der Threads...

CS sind dafür geeigent, bestimmte Dinge gezielter zu synchronisieren... z.B. 2 unterschiedliche Resourcen, die von mehreren Threads gelesen/beschrieben werden... Wenn jede Resource eine eigene CriticalSection besitzt, wird mit der jeweiligen CS der Schreib/Lesezugriff auf diese eine Resource serialisiert... ohne dabei Threads zu behindern, welche andere Resourcen und Critical Sections maltretieren...

Dabei versucht dann jeder Thread die Resource für sich zu reservieren...Im Falle, dass sie bereits reserviert ist, muss er warten (TryEnterCriticalSection wäre das nicht-blockierende Pendant, aber nur NT und auch nicht in der Klasse TCriticalSection enthalten.)
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
   _______________
  |               |
  | Thread A      |                    __________
  | CS1.Enter----------------.        |          |        ____________
  |_______________|          |        | CS 1     |       |            |
   _______________           '----------------------------> Daten I   |
  |               |          ,------------>X     |       |____________|
  | Thread B      |          |        |__________|
  | CS1.Enter----------------'
  |_______________|
   _______________
  |               |
  | Thread C      |                    __________
  | CS2.Enter----------------.        |          |        _____________
  |_______________|          |        | CS 2     |       |             |
   _______________           '----------------------------> Daten II   |
  |               |          ,------------>X     |       |_____________|
  | Thread D      |          | ,---------->X     |
  | CS2.Enter----------------' |      |__________|
  |_______________|            |
   _______________             |
  |               |            |
  | Thread E      |            |
  | CS2.Enter------------------'
  |_______________|



   ---> Reservierungsanfrage
   -->X Anfrage wird gehalten,
        bis Resource wieder
        freigegeben wird
        (CS.Enter blockiert)

der Nachteil bei Critical Sections ist, dass sie auch Lesezugriffe serialisieren: d.h. wenn kein Thread schreibt, dafür alle lesen, dann kommt sich eigentlich keiner ins Gehege... also bedarf es dann
auch keiner Synchronisierung...

Bei der CS müssen aber dennoch alle Lesezugriffe konsequent synchronisiert werden, da man nicht lesen darf, wenn gerade wer schreiben KÖNNTE. Das Problem dabei ist eben, dass bei der reinen CS keine Fallunterscheidung stattfindet... ob nun wer schreibt oder nicht und somit der Fluss immer wieder aufgehalten wird...
das macht das Ganze also oftmals unperformant...

Um mehrere "parallele" Lesezugriffe zu ermöglichen und Schreibzugriffe zu serialisieren, hat Borland den TMultiReadExclusiveWriteSynchronizer (MREW) implementiert, welcher intern ebenfalls eine CS nutzt + Fallunterscheidung.
(Der MREW soll allerdings Deadlock-Effekte aufweisen, laut Borland QC und NG. Ich weiß garnicht mehr, wie die offzielle Stellungsnahme von Borland dazu war... Entweder man sucht eine Alternative, schustert sich selbst was zusammen oder man verwendet weiterhin MREW und hofft... (die VCL nutzt selbst teilweise MREW...))

wie motzi bereits erwähnte: wichtig ist das Leave (CS), EndWrite/Read (MREW) im Finally-Block... zur Not kann man auch dort mit der Funktion ExceptObject auf Exceptions reagieren... (on = is usw.) alternativ kann man auch den Referenzzähler von Schnittstellen misbrauchen... bei Funktionsaustritt und damit verlorener Referenz: Unlock... is aber nich unbedingt schön und birgt Fehlerquellen... (aber netter Effekt für Restore-Objekte anderer Art...)

_________________
"...haben uns verirrt, kommen aber gut voran" (Tom DeMarco)