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

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

11

25.06.2008, 17:23

Naja auch eine bool Variable kann gefährlich sein (ich gehe davon aus, dass du das weißt und anders meinst):

C-/C++-Quelltext

1
2
3
4
5
6
if(ist_frei) 
{
ist_frei = false;
[...]
ist_frei = true;
}


Thread 1: if(ist_frei) => geht in den Block rein, Thread wechselt
Thread 2: if(ist_frei) => geht in den Block rein, fängt an zu arbeiten, Thread wechsel
Thread 1: ist ja noch im Block und fängt auch anzuarbeiten
*BOOM*

:badgrin:
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

12

25.06.2008, 18:14

jo, das ist mir klar... aber ich hab ja irgendwo sinngemäß geschrieben, dass Thread1 auf true und Thread2 auf false reagiert - nix mit 'ist_frei' :)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool trigger;
void Thread1()
{
 while (trigger)
  Sleep(0);

 [arbeite]

 trigger = true;
}


void Thread2()
{
 while (! trigger)
  Sleep(0);

 [arbeite]

 trigger = false;
}


Also ein Thread wartet solange es true ist und setzt nach getaner Arbeit (von false) auf true, der andere wartet solange false ist und setzt nach Arbeit auf false. Deswegen hatt ich ja die Einschränkung gebracht

Zitat

... genau 2 Threads in einer Form syncronisieren will, dass immer erst der eine und dann der andere dran ist

rklaffehn

Treue Seele

Beiträge: 267

Wohnort: Braunschweig

  • Private Nachricht senden

13

25.06.2008, 18:36

Hrhr, bei Threads denke ich immer etwas puristisch. Denn im Vergleich zu einem Dead-Lock ist eine Race-Condition so richtig ekelig (Originalausdruck von der Redaktion ausgetauscht ;)). Also: lieber gleich richtig programmieren und später nicht ärgern. Aber es stimmt schon, ein Mutex ist schon ein schweres Geschütz und sollte nicht unnütz eingesetzt werden.

Speicheroperationen aus C++ (und anderen Hochsprachen) sind in der Regel übrigends nicht atomar. Das ist fast immer Load - Modify - Store = 3 Operationen; außer bei lokalen Variablen, die komplett in einem Register optimiert sind, und die zählen hier nicht.

Btw. wenn nur ein Thread auf eine Variable zugreift, kann man damit auch keine Threads synchronisieren... :D Und wenn zwei Threads so synchronisiert sind, dass garantiert immer nur einer aktiv ist, dann brauche ich keine zwei Threads.
God is real... unless declared integer.
http://www.boincstats.com/signature/user_967277_banner.gif

xardias

Community-Fossil

  • »xardias« ist der Autor dieses Themas

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

14

25.06.2008, 19:54

Zitat von »"rklaffehn"«


Speicheroperationen aus C++ (und anderen Hochsprachen) sind in der Regel übrigends nicht atomar. Das ist fast immer Load - Modify - Store = 3 Operationen; außer bei lokalen Variablen, die komplett in einem Register optimiert sind, und die zählen hier nicht.

Btw. wenn nur ein Thread auf eine Variable zugreift, kann man damit auch keine Threads synchronisieren... :D Und wenn zwei Threads so synchronisiert sind, dass garantiert immer nur einer aktiv ist, dann brauche ich keine zwei Threads.

Danke, wieder was gelernt. Ich habe noch ziemlich wenig Erfahrung mit dem Thema, aber ich werde nächstes Semester ein paar Veranstaltungen dazu rein packen.

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

15

25.06.2008, 20:42

Zitat von »"rklaffehn"«


Btw. wenn nur ein Thread auf eine Variable zugreift, kann man damit auch keine Threads synchronisieren... :D Und wenn zwei Threads so synchronisiert sind, dass garantiert immer nur einer aktiv ist, dann brauche ich keine zwei Threads.

Hmpf, das is nur nen Beispiel... denk dir einfach im Thread2 anstelle von Sleep(0) andere Aufgaben die nicht syncronisiert werden müssen und im Thread1 einen Programmablauf, in dem halt ab und an mal Nachrichten an Thread2 geschickt werden müssen (die dann wieder in die unabhängige Bearbeitung einfließen...)

Und bitte jetzt nicht wieder das Beispiel hernehmen um die Sinnlosigkeit vom Prinzip zu erläutern xD
Es sollte inzwischen klar sein, dass das nicht der normale Weg für die Aufgabe ist.


// €dit: vergesst den Rest [€dit2: doch nich vergessen xD]


Um mal noch was zum Thema beizutragen... hab vor kurzem mal ne Klasse geschrieben, um Lese-und Schreibrechte in andere Klassen per Vererbung implementieren zu können.
Die Idee ist, genau einen Schreibzugriff oder beliebig viele Lesezugriffe gleichzeitig zu erlauben.

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
class CriticalSectionManager
{
protected:

    CriticalSectionManager()
    {
        _initCriticalSectionManager();
    }

    CriticalSectionManager(const CriticalSectionManager&)
    {
        _initCriticalSectionManager();
    }

    ~CriticalSectionManager()
    {
        DeleteCriticalSection(&_guard);
        DeleteCriticalSection(&_access);
    }

    CriticalSectionManager& operator =(const CriticalSectionManager& other)
    {
        return *this;
    }


public:

    void getReadaccess () const
    {
        EnterCriticalSection(&_guard);

        BOOL result = TryEnterCriticalSection(&_access);
        if (result == FALSE &&
            InterlockedIncrement(&_read_access_count) == 1)
        {
            EnterCriticalSection(&_access);
        }
        else if (result == TRUE)
        {
            InterlockedIncrement(&_read_access_count);
        }

        LeaveCriticalSection(&_guard);
    }


    void getWriteaccess()
    {
        EnterCriticalSection(&_access);
    }


    void releaseReadaccess () const
    {
        if (InterlockedDecrement(&_read_access_count) == 0)
            LeaveCriticalSection(&_access);
    }


    void releaseWriteaccess()
    {
        LeaveCriticalSection(&_access);
    }


private:

    void _initCriticalSectionManager()
    {
        _read_access_count = 0;
        InitializeCriticalSection(&_guard);
        InitializeCriticalSection(&_access);
    }

    mutable CRITICAL_SECTION _guard, _access;
    mutable LONG _read_access_count;
};


€ditX: hab mal noch ne nicht mehr benötigte Variable rausgenommen - hatte vorher ja schon andere Ansätze mit Denkfehlern^^

xardias

Community-Fossil

  • »xardias« ist der Autor dieses Themas

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

16

25.06.2008, 22:34

Genau so ein Nachrichtenähnliches System habe ich im Sinn.

Ein Steuerthread kann den Thread in verschiedene Zustände setzen (prepare, run, clean), wartet aber falls er Thread noch nicht mit dem bearbeitet des vorherigen Zustands fertig ist. Dazu wird es auf jeden Fall ein Mutex geben.

Doch es gibt Fälle in denen der Steuerthread ein neuen Zustand postet bevor der Thread überhaupt Gelegenheit hatte den Mutex zu locken. Daher die zusätzliche Variable die anzeigt ob der neue Zustand angenommen wurde.

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

17

26.06.2008, 11:27

Zitat von »"grek40"«

jo, das ist mir klar... aber ich hab ja irgendwo sinngemäß geschrieben, dass Thread1 auf true und Thread2 auf false reagiert - nix mit 'ist_frei' :)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool trigger;
void Thread1()
{
 while (trigger)
  Sleep(0);

 [arbeite]

 trigger = true;
}


void Thread2()
{
 while (! trigger)
  Sleep(0);

 [arbeite]

 trigger = false;
}


Also ein Thread wartet solange es true ist und setzt nach getaner Arbeit (von false) auf true, der andere wartet solange false ist und setzt nach Arbeit auf false. Deswegen hatt ich ja die Einschränkung gebracht

Zitat

... genau 2 Threads in einer Form syncronisieren will, dass immer erst der eine und dann der andere dran ist

Dann aber nicht vergessen, trigger als volatile zu markieren!
Wenn man dann VC05 oder höher benutzt, sollte man damit auch auf Multicores keine Probleme haben, wenn man einen anderen Compiler benutzt könnte es auf Multicores schwierig werden.
Siehe auch hier.

Ciao
Sei stets geduldig gegenüber Leuten, die nicht mit dir übereinstimmen. Sie haben ein Recht auf ihren Standpunkt - trotz ihrer lächerlichen Meinung. (F. Hollaender)

xardias

Community-Fossil

  • »xardias« ist der Autor dieses Themas

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

18

26.06.2008, 11:59

Danke für den Hinweis, ich fürchte, das hätte mich sehr schnell in Teufels Küche gebracht ohne volatile. Ich habe übrigends ein netten kleinen Artikel dazu gefunden:

http://www.ddj.com/cpp/184403766

Werbeanzeige