Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

xardias

Community-Fossil

  • »xardias« ist der Autor dieses Themas

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

1

24.06.2008, 10:36

pthread: Warten auf variable

Hallo allerseits,

zur Threadsynchronisation würde ich gerne einen Thread darauf warten lassen, dass ein anderer eine Variable gesetzt hat. (Thread A signalisiert Thread B, dass er weiterarbeiten kann)
Dazu gibt es bekanntlich pthread-conditions, doch die haben ein Problem. Es funktioniert nur wenn Thread B schon darauf wartet, dass Thread A das signal gibt. Ist dieser noch am arbeiten und kommt an die Stelle nachdem Thread A das signal gegeben hat wartet er sich zu tode.

Also wäre es das einfachste eine einfache bool Variable zu haben, welche gesetzt wird sobald Thread B weiterarbeiten darf. Ich würde gerne wissen wie sowas implementiert wird. Die pthread mutex und condition methoden blockieren den Thread ja auch bis zu einem gewissen Zeitpunkt, also müsste man sowas doch auch selbst implementieren können.

C-/C++-Quelltext

1
while(!var) shed_yield();

Wäre mein naiver Ansatz. Wird der mir Probleme bereiten? Threadsynchronisatzion lässt sich so schwierig testen und ich würde gerne ein Fehler darin ausschließen ;).

Grüße,
Dennis

Beneroth

Alter Hase

Beiträge: 969

Wohnort: Schweiz

Beruf: Software Entwickler

  • Private Nachricht senden

2

24.06.2008, 11:37

hm, deine bool variable solltest du aber auch mit einem Mutex absichern, sodass nicht beide Threads gleichzeitig an der fummeln. Bei nem Bool und nur einem Core ist das zwar relativ unwahrscheinlich, sobald du aber mehrere Kerne oder CPUs hast durchaus möglich..

und selbstmit shed_yield() kriegste, zumindest war es bei mir so, auch schnell ne hohe CPU Auslastung, schick den Thread da lieber ne gewisse Zeit schlafen, z.B. mit nanosleep.


btw., ich hab momentan das problem das beim locken eines Mutexes (Mutexes? Genitiv?) ne Speicherzugriffsverletzung krieg :roll:
Vielleicht weil ich die Mutex-Variable durch etwa 3 Threads durchschleusse :?

xardias

Community-Fossil

  • »xardias« ist der Autor dieses Themas

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

3

24.06.2008, 11:49

Jupp, also der Zugriff ist auf jeden Fall gesichert, da nur ein Thread schreiben darf.
Dann werde ich das mal mit nanosleep probieren.

Das einzige was mir zu deinem Problem einfallen würde ist: Hast du den Mutex auch initialisiert? Sonst sollte es eigentlich keine Probleme machen den in 3 Threads zu benutzen.

Beneroth

Alter Hase

Beiträge: 969

Wohnort: Schweiz

Beruf: Software Entwickler

  • Private Nachricht senden

4

24.06.2008, 13:08

Zitat von »"xardias"«

Das einzige was mir zu deinem Problem einfallen würde ist: Hast du den Mutex auch initialisiert? Sonst sollte es eigentlich keine Probleme machen den in 3 Threads zu benutzen.


Ja, obs er tatsächlich ist muss ich noch testen. Es ging an anderer Stelle, also müsste dort auch gehen. Bin aber seit vorgestern nicht daran gekommen noch detailierter zu debuggen ;)

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

5

24.06.2008, 15:10

Ich dacht nen Mutex wird in jedem Thread lokal geöffnet und nich irgendwie 'durchgeschleust'?

// Zu der Sache mit der bool Variable: Ich würd sagen die Absicherung ist nur nötig, wenn es ne Chance gibt, dass mehrere Schreibzugriffe zugleich kommen... wenn absolut klar ist, dass nur ein Thread schreibt dann gehts auch so (z.b. Thread 1 setzt nur auf false wenn var == true und Thread 2 was tun soll, Thread 2 setzt nur auf true, wenn var == false und die Aufgabe erledigt wurde)

rklaffehn

Treue Seele

Beiträge: 267

Wohnort: Braunschweig

  • Private Nachricht senden

6

25.06.2008, 12:35

Hi, wenn man das richtig programmiert, funktioniert das auch mit Conditions hervorragend.

C-/C++-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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Thread 1

class T1
{
public:
  T1 ()
  : _continue (false),
    _c (&m) // zu jeder Condition gehört ein Mutex

  {
  }

  void setContinueFlag ()
  {
    _m.lock (); // Zugriff sichern.

    _continue = true; // Status ändern.

    _c.signal (); // ggf. einen Schläfer aufwecken (sonst broadcast für alle)

    _m.unlock (); // Zugriff freigeben

  }

private:

  void run ()
  {
    _m.lock (); // Zugriff absichern

    while (! _continue) // Variable prüfen und ggf. schlafen legen

      _c.wait (); // Wenn nicht gesetzt, schlafen legen (implizites unlock/lock bei schlafen/aufwachen). 

    _m.unlock (); // Zugriff fertig.


    // mach was und fertig.

  }

  bool _continue;
  Mutex _m;
  Condition _c;
};

// Thread 2

class T2
{
public:

  T2 (T1* other)
  : _other (other)
  {
  }

private:

  void run ()
  {
    // mach was

    _other->setContinueFlag (); // Jetzt kann _other loslegen.

  }

  T1* _other;
};


Quintessenz:
* Wenn ich mit einer Condition auf eine Variable warte, muss ich immer auch die Variable prüfen, und zwar auch dann, wenn ein "wait" aufgewacht ist.
* Ohne Mutex geht hier gar nichts, da für solche Signale immer mehrere Threads auf die selbe Variable zugreifen müssen. Selbst wenn einer nur liest und der andere nur schreibt muss ein Mutex her. Das Posting von grek40 ist hier etwas gefährlich :)
* Kapsele Mutex und Condition möglichst in Methoden, dann kann man da leichter was dran ändern und Aufrufer müssen nicht jedesmal selbst aufpassen.
* die entsprechenden "man"-Pages geben auch Auskunft über sowas
* ja, das ist Pseudocode :D
God is real... unless declared integer.
http://www.boincstats.com/signature/user_967277_banner.gif

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

7

25.06.2008, 12:43

@rklaffehn Nach meinem Kenntnisstand stimmt das was grek40 gesagt hat. Daher wundert mich deine Aussage, dass das gefährlich wäre. Vorallem sind Mutex nach meinen Kenntnisstand nicht gerade Leichtgewichte und arbeiten im Endeffekt wahrscheinlich auch "nur" mit lock + cmpxchg und Konsorten.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

xardias

Community-Fossil

  • »xardias« ist der Autor dieses Themas

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

8

25.06.2008, 14:23

Also, dass ein Mutex nötig ist, wenn nur ein Thread in eine bool variable schreibt wäre mir auch neu. Soweit ich weiß sind Speicheroperationen atomic, und auch wenn man mehrere CPUs hat sollte es da keinerlei Probleme geben.

Aber die Kombination von condition+variable gefällt mir, das werde ich mir mal in eine kleine Klasse kapseln denke ich. Dank dir.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

9

25.06.2008, 15:50

Naja. Kommt drauf an, was du als Speicheroperationen ansiehst. CMPXCHG ist z.B. nur dann atomar, wenn man vorher ein LOCK Signal setzt.

Quelle: http://faydoc.tripod.com/cpu/lock.htm
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

10

25.06.2008, 16:23

Mir ist klar, dass meine Variante gefährlich werden könnte, sobald man das irgendwie erweitert, aber so wie es is seh ich die Gefahr nicht, da ein bool eben selbst wenn man gleichzeitig liest und schreibt nur true oder false sein kann... erst bei einer Variable die mehr als 2 Zustände haben kann besteht die rein theoretische Möglichkeit, dass ein Zustand ausgelesen wird, der weder demjenigen vor dem Schreibzugriff noch dem dannach entspricht.

Sobald man auch nur bisschen flexibel sein will würd ich sowas also nicht machen, wenn man aber mal ohne großen Overhead genau 2 Threads in einer Form syncronisieren will, dass immer erst der eine und dann der andere dran ist dann is das halt ne denkbare Variante.

Werbeanzeige