Twitter und Facebook-Anbindung
X
Tweet Follow @twitterapi
!!! Anbindung an twitter und facebook öffnen !!!

Wenn Ihnen mein Online-Buch gefällt,
dann bedanken Sie sich doch mit einer kleinen Spende...

32.1 Semaphore mit Hilfe der Win API

32.1 Semaphore mit Hilfe der Win API

In diesem Beispiel werde ich drei Threads beauftragen, etwas auf der Konsole auszugeben, wobei ich es nur zwei von ihnen gestatte, in den kritischen Abschnitt einzutreten. Als Resultat sollte man dann in der Ausgabe sehen, dass sich zunächst zwei Threads abwechseln und ganz am Ende erst der Dritte alleine seine Ausgabe macht, weil er die ganze Zeit warten musste. Damit die Sache übersichtlich bleibt, machen alle Threads jetzt nur noch fünf Ausgaben.

 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
					
#include <windows.h>
#include <stdio.h>
#include "ThreadWrapper.h"

struct SMyThreadData {
	int	iStart;
	int	iEnd;
	int	iID;
	HANDLE	hSemaphor;
};



// Funktion welche durch den Thread ausgeführt wird ///////////////////////////
DWORD ThreadFunc(CThreadWrapper<SMyThreadData>* pThread) {
	__try {
		WaitForSingleObject(pThread->GetData().hSemaphor, INFINITE);

		for (int iCount = pThread->GetData().iStart; iCount < pThread->GetData().iEnd && !pThread->IsTerminated(); iCount++) {
			printf("Thread: %i - %i\n", pThread->GetData().iID, iCount);
			Sleep(100);
		} // end of for
	} __finally {
		ReleaseSemaphore(pThread->GetData().hSemaphor, 1, NULL);
	} // end of try

	return 0;
} // ThreadFunc ///////////////////////////////////////////////////////////////
  


// Hauptfunktion der Anwendung ////////////////////////////////////////////////
int main(int argc, char** argv) {
	HANDLE				hSemaphor	= CreateSemaphore(NULL, 2, 2, NULL);

	SMyThreadData			sData1		= {0, 5, 1, hSemaphor};
	SMyThreadData			sData2		= {1000, 1005, 2, hSemaphor};
	SMyThreadData			sData3		= {10000, 10005, 3, hSemaphor};

	CThreadWrapper<SMyThreadData>*	pThread1	= new CThreadWrapper<SMyThreadData>(&ThreadFunc, sData1);
	CThreadWrapper<SMyThreadData>*	pThread2	= new CThreadWrapper<SMyThreadData>(&ThreadFunc, sData2);
	CThreadWrapper<SMyThreadData>*	pThread3	= new CThreadWrapper<SMyThreadData>(&ThreadFunc, sData3);

	printf("START\n");

	pThread1->Resume();
	pThread2->Resume();
	pThread3->Resume();

	// Warten, bis alle Threads fertig sind
	while (!pThread1->IsFinished() || !pThread2->IsFinished()) Sleep(1);

	delete pThread1;
	delete pThread2;
	delete pThread3;

	CloseHandle(hSemaphor);
	
	printf("ENDE\n");

	return 0;
} // main /////////////////////////////////////////////////////////////////////
					

Ausgabe:

START
Thread: 1 - 0
Thread: 2 - 1000
Thread: 1 - 1
Thread: 2 - 1001
Thread: 1 - 2
Thread: 2 - 1002
Thread: 1 - 3
Thread: 2 - 1003
Thread: 1 - 4
Thread: 2 - 1004
Thread: 3 - 10000
Thread: 3 - 10001
Thread: 3 - 10002
Thread: 3 - 10003
Thread: 3 - 10004
ENDE
		

Bis einschließlich Zeile 23 ist wieder alles so, wie vorhin bei den Mutexen. Ich benutze wieder ein Handle und rufe auch wieder "WaitForSingleObject" auf, um in den kritischen Abschnitt zu gelangen.

Erst ab Zeile 24 gibt es einen kleinen Unterschied. Hier wird jetzt der Abschnitt wieder verlassen, aber man kann hier der entsprechenden Funktion auf einmal mehrere Parameter übergeben. Im Grunde ist der dritte Parameter meist unwichtig und als zweiten Parameter gibt man "1" an. Aber für was steht die 1? Bei einer Semaphore können ja immer nur eine feste Anzahl von Threads in einen solchen Abschnitt eintreten. Wie viele eingetreten sind wird mitgezählt. Wenn man jetzt austritt, muss man sagen, wie viele austreten und das ist im Normalfall einer. Es kann jedoch vorkommen, dass zwei Threads in diesem Bereich sind und einer den anderen terminiert. Da der Andere jetzt keine Chance mehr hatte den Abschnitt offiziell zu verlassen, kann der erste Thread, beim verlassen des Abschnittes, dem Betriebssystem mitteilen, dass jetzt insgesamt zwei weniger da sind.

In Zeile 33 wird jetzt die Semaphore angelegt. Hier gibt es jetzt etwas zu beachten. Wie Sie sich denken können, kommt jetzt natürlich ein Parameter hinzu, mit welchen man sagen kann, wie viele die Semaphore benutzen können. Außerdem hat man wieder die Möglichkeit, den kritischen Abschnitt blockiert zu Erzeugen, wobei man diese Angabe genau anders herum zu verstehen hat, als bei den Mutexen. Initialisiert man einen Mutex mit 1, heißt dies, es ist einer im kritischen Abschnitt drin und somit kann kein anderer. Initialisiert man die Semaphor mit 1, heißt dies, dass noch einer kann, weil es noch eine Kugel in der Schale gibt oder weil noch ein Schlüssel an der Wand hängt. Ich erlaube also zwei Threads den Zugriff (erlaube maximal zwei Kugeln) und sage, dass momentan zwei Threads können (ich lege diese zwei Kugeln in die Schale).

Zum Seitenanfang
Zum Inhaltsverzeichnis

© Copyright by Thomas Weiß, 2009 - 2012