Autor |
Beitrag |
alias5000
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: Do 24.01.08 19:48
Hallo,
ich habe eine Verständnisfrage zu TCriticalSection(CS).
Und zwar verstehe ich diese Komponente bisher so, dass ein Codeblock, der von einer CS-Instanz geschützt wird (Enter-Leave), nur für einen Thraed zugänglich ist.
Die Frage ist jetzt, ob dieser Zugriffsschutz Code-Block-weit, oder CS-Instaz-weit gilt.
Die Frage ist, ob ein Thread1, der Methode 1 ausführen will, während Thread2 Methode2 ausführt, von der CS geblockt wird, oder nicht, bis Thread zwei raus aus der CS ist.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| cs: TCriticalSection;
... cs := TCriticalSection.Create; ...
procedure Methode1; begin cs.Enter; Schreibevariable(); cs.Leave; end;
procedure Methode1; begin cs.Enter; Lesevariable(); cs.Leave; end; |
(Oder ganz kurz gesagt, ich suche den praktischen Sinn von cs's)
Gruß
alias5000
_________________ Programmers never die, they just GOSUB without RETURN
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Do 24.01.08 20:58
Die Ciritical Sections stellen sicher, dass immer nur ein Thread auf bestimmte Ressourcen zugreift.
Beispiel:
Thread1 betritt CS1 und fängt an, an Objekt x zu werkeln
Thread2 möchte jetzt auch an Objekt x rumwerkeln. Wenn er das einfach so anfängt, gibt es Probleme - die beiden Threads hauen sich dann gegenseitig auf die Finger und Objekt x geht z.B. kaputt. Wenn Thread 2 auch die CS1 benutzt, dann bekommt der die Meldung "du musst jetzt erstmal warten, da ist grad jemand anders am basteln". Das tut er dann, bis Thread1 die CS verlässt und damit signalisiert, dass die Ressourcen wieder frei für andere sind.
Critical Sections haben also den Sinn, dass immer nur ein Thread auf gewisse Bereiche (z.B. Objekte im Speicher) zugreift. Man sollte aber darauf achten, dass tatsächlich alle Zugriffe auf dieses schützenswerte Objekt über Critical Sections ablaufen.
Die Antwort auf deine Frage wäre also "Ja." Thread 1 wird geblockt, bis Thread 2 fertig ist. Afaik fängt er dann aber automatisch an, d.h. man muss nicht in einer Schleife den Aufruf immer wieder starten.
_________________ We are, we were and will not be.
|
|
dummzeuch
      
Beiträge: 593
Erhaltene Danke: 5
Delphi 5 ent, Delphi 6 bis Delphi XE8 pro
|
Verfasst: Do 24.01.08 23:08
alias5000 hat folgendes geschrieben: | Hallo,
ich habe eine Verständnisfrage zu TCriticalSection(CS).
Und zwar verstehe ich diese Komponente bisher so, dass ein Codeblock, der von einer CS-Instanz geschützt wird (Enter-Leave), nur für einen Thraed zugänglich ist.
|
Und das gilt auch fuer aus diesem Code-Block aufgerufene Funktionen/Methoden.
Zitat: |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| cs: TCriticalSection;
... cs := TCriticalSection.Create; ...
procedure Methode1; begin cs.Enter; Schreibevariable(); cs.Leave; end;
procedure Methode1; begin cs.Enter; Lesevariable(); cs.Leave; end; |
Die Frage ist, ob ein Thread1, der Methode 1 ausführen will, während Thread2 Methode2 ausführt, von der CS geblockt wird, oder nicht, bis Thread zwei raus aus der CS ist.
|
Ja, er wird geblockt, bis Thread zwei cs.Leave aufgerufen hat.
twm
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 24.01.08 23:23
Gausi hat folgendes geschrieben: | Afaik fängt er dann aber automatisch an, d.h. man muss nicht in einer Schleife den Aufruf immer wieder starten. |
Ja, das ist so, und die API-Funktionen dazu arbeiten ebenfalls so. EnterCriticalSection reserviert die Benutzung der Sektion und wartet ggf. so lange bis diese frei ist. LeaveCriticalSection verlässt diese wieder.
Zusätzlich gibt es TryEnterCrticalSection. Diese Funktion wartet nicht, sondern versucht nur die Sektion zur Benutzung zu reservieren. Der Erfolg oder Misserfolg wird zurückgegeben. Dadurch kann man unerwünschte Blockierungen umgehen.
Bei TCriticalSection gibt es TryEnter, das dem Namen nach zu urteilen diese Funktion bietet. (Ausprobiert oder angesehen habe ich mir das aber nicht.)
|
|
alias5000 
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: Fr 25.01.08 18:46
Das ist ja klasse. Das heißt, dass sie CS sogar schaut, welche Ressourcen ich in den Blöcken verwende und nicht nur einfach danach schaut, ob in CS1 ein Thread "schon drin ist" und danach gehend blockt
korrekt?
Gruß
alias5000
_________________ Programmers never die, they just GOSUB without RETURN
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Fr 25.01.08 18:54
alias5000 hat folgendes geschrieben: | Das heißt, dass sie CS sogar schaut, welche Ressourcen ich in den Blöcken verwende |
Nein. Eine spezielle CS ist dafür da, um eine bestimmte Ressource so zu schützen, dass immer nur ein Thread Zugriff hat. Ein Beispiel wo es kracht, oder krachen kann:
Thread A beginnt CS A und werkelt darin an Ressource A und B
Thread B beginnt CS B und werkelt darin an Ressource B und C.
Obwohl Thread 1 an Ressource A und B rummacht, kann auch Thread 2 an B rummachen. Da muss man dann als Programmierer schon aufpassen  .
Und bei Verschachtelten CS muss man zusätzlich darauf achten, dass man keine Deadlocks produzieren kann.
_________________ We are, we were and will not be.
|
|
alias5000 
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: Fr 25.01.08 19:02
hm, dann habe ich das noch nicht richtig verstanden.
Aus welchen Grund kracht es in deinem Beispiel (das "krachen kann" kommt ja wegen einem anderen Grund, daher lasse ich diese Form grad mal weg)?
Gruß
alias5000
_________________ Programmers never die, they just GOSUB without RETURN
|
|
UGrohne
      

Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Fr 25.01.08 19:14
Die CritialSection macht im Endeffekt gar nichts mit den Ressourcen, auf die Du zugreifst. Wenn einer Deiner Threads in einer CriticalSection geht (also das Enter aufruft), prüft dieses Objekt, ob bereits jemand "drin" ist. Wenn ja, wartet diese Methode so lange, bis der andere Thread die CS wieder verlassen hat und beendet diese Methode dann, sodass der aufrufende Thread dann weiter arbeitet. Er zwingt den aufrufenden sozusagen dazu, solange zu warten, bis der Weg frei ist. Es gibt keinerlei Methoden dabei, irgendwelche Resourcen zu schützen.
D.h. auch, dass Du wirklich ALLE Zugriffe auf die zu schützende Resource über EINE Instanz der CriticalSection laufen lassen musst, sonst funktioniert das nicht.
|
|
alias5000 
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: Fr 25.01.08 19:18
Ich glaub jetzt hab ichs dann aber.
Zur Sicherheit nochmal die Nachfrage:
Das bedeutet, der Schutz durch die CS ist "Instanz"-orientiert und nicht "Codeblock"-orientiert.
Ich will damit folgendes sagen:
Wenn irgendwo ein Thread ein CS1.Enter (CS1 als Instanz einer CS) ausführt, kann ein anderer Thread einen anderen durch CS1 geschützten Codeblock nicht ausführen, bis CS1 den ersten mit Leave freigibt.
So?
Gruß
alias5000
_________________ Programmers never die, they just GOSUB without RETURN
|
|
Sinspin
      
Beiträge: 1335
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: Fr 25.01.08 20:05
alias5000 hat folgendes geschrieben: |
Wenn irgendwo ein Thread ein CS1.Enter (CS1 als Instanz einer CS) ausführt, kann ein anderer Thread einen anderen durch CS1 geschützten Codeblock nicht ausführen, bis CS1 den ersten mit Leave freigibt.
|
ja, aber nur dann wenn der andere Thread auch CS1.Enter aufruft, denn da drinne bleibt er dann stecken.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 25.01.08 20:07
alias5000 hat folgendes geschrieben: | Wenn irgendwo ein Thread ein CS1.Enter (CS1 als Instanz einer CS) ausführt, kann ein anderer Thread einen anderen durch CS1 geschützten Codeblock nicht ausführen, bis CS1 den ersten mit Leave freigibt. |
Richtig. Problematisch wird es was die bereits angesprochenen Deadlocks angeht, wenn du zum Beispiel mit Thread A etwas aus Resource X liest und zu Resource Y hinzuaddierst. Dafür musst du ja beide sperren. Jetzt stell dir vor, ein Thread B braucht Resource Y und später Resource X. Beide Threads laufen ja gleichzeitig. Jetzt reserviert Thread A die Resource X, dann wird Thread B fortgesetzt. Dieser reserviert jetzt Resource Y. Jetzt wartet Thread A auf Resource Y und Thread B auf Resource X...
Das ist ein konstuiertes Beispiel, aber das dient auch nur zur Verdeutlichung, in der Praxis passiert sowas in komplexeren Multithreadanwendungen auch undurchschaubarer.
Es gibt übrigens auch den TMultiReadExclusiveWriteSynchronizer, mit dem du beliebig lesen kannst, und das Lesen wird nur gesperrt, wenn gerade geschrieben wird. Denn ansonsten ist paralleles Lesen ja ungefährlich.
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Fr 25.01.08 20:32
Einige Anmerkungen
1. Critical Sections sind sehr 'leichtgewichtig', verbraten also kaum CPU-Zeit.
2. CS blocken nur unterschiedliche Threads, innerhalb eines Threads kann aber mehrmals auf die CS zugreifen.
_________________ Na denn, dann. Bis dann, denn.
|
|
alias5000 
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: Fr 25.01.08 21:20
jetzt ist es klar
Viele Dank auch für die Zusatzinfos, jetzt traue ich mich da endlich mal gescheit ran (alles Multi-gethreste von war bisher immer so unabhängig von Synchronisation, dass ich das nie gebraucht habe und bis jetzt ja auch nicht wirklich verstanden habe, weil überall derselbe Vergleich vom "Tor" verwendet wird  )
Gruß
alias5000
_________________ Programmers never die, they just GOSUB without RETURN
|
|
|