PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++ Multithreading und Mutex beim Dateischreiben


mobius
2008-07-09, 10:32:40
Morgen Leute,

hier mein kleines Testprogramm. 5 Threads werden erzeugt und schreiben in eine Datei verschiedene Ausgaben. Da Dateischreiben ja ein kritischer Abschnitt ist, versuche ich mit einem Mutex den Zugriff auf jeweils einen Thread zu begrenzen, aber irgendwie komm ich grad nicht dahinter.

Das Programm erfüllt keinen Sinn, sondern dient nur Testzwecken für ein Folgeprogramm, falls sich Jemand wundert.
C++ ist auch nicht gerade meine Sprache.


#include <windows.h>

#include <conio.h>
#include <ctype.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream.h>
#include <math.h>

//Header declarations
DWORD WINAPI testprozedur1(LPVOID data);
DWORD WINAPI testprozedur2(LPVOID data);
DWORD WINAPI testprozedur3(LPVOID data);
DWORD WINAPI testprozedur4(LPVOID data);
DWORD WINAPI testprozedur5(LPVOID data);

FILE* fp;

void main(void)
{

fp = fopen("test.txt","w");
HANDLE hThread[5];
DWORD dwThreadID[5];

hThread[0] = CreateThread(NULL,0,testprozedur1,(LPVOID)0,0,&dwThreadID[0]);
hThread[1] = CreateThread(NULL,0,testprozedur2,(LPVOID)1,0,&dwThreadID[1]);
hThread[2] = CreateThread(NULL,0,testprozedur3,(LPVOID)2,0,&dwThreadID[2]);
hThread[3] = CreateThread(NULL,0,testprozedur4,(LPVOID)3,0,&dwThreadID[3]);
hThread[4] = CreateThread(NULL,0,testprozedur5,(LPVOID)4,0,&dwThreadID[4]);

//wait for all threads to complete before continuing
WaitForMultipleObjects(5, hThread, TRUE, INFINITE);
//Display a messagebox to show that the Wait state has finished
//MessageBox(NULL,"This Messagebox is to show that all threads have completed.","Messagebox", NULL);
//close handles
CloseHandle(hThread[0]);
//end the main function

fclose(fp);
}

void schreiben(int i)
{
HANDLE hMutex = CreateMutex(NULL, // wir brauchen anfangs keinen Security descriptor
FALSE, // das Mutex gehört anfangs nicht gleich uns
"MeinMutex"); // irgend ein mutex name, der möglichst eindeutig (unique) sein sollte..
if (!hMutex)
{
// Mutex erstellen fehlgeschlagen...
// sollte hofftl nie passieren..
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// ein anderer Prozess hat das Mutex schon erstellt,
// ist aber kein Problem, wir können das Handle trotzdem benutzen
// ist interessant, falls du Single-Instance-Programme haben willst
}
// jetzt kannst du mit dem Mutex arbeiten:
if ((WaitForSingleObject(hMutex, 20) != WAIT_TIMEOUT) & (GetLastError() != ERROR_ALREADY_EXISTS))
{
// jetzt gehört das Mutex uns
// wir arbeiten an der Ressource
cout << i;
switch(i)
{
case 1:
fprintf(fp, ".");
break;
case 2:
fprintf(fp, "x");
break;
case 3:
fprintf(fp, "o");
break;
case 4:
fprintf(fp, "-");
break;
case 5:
fprintf(fp, "|");
break;
}

// und nach getaner Arbeit geben wir das Mutex wieder frei,
// damit ein anderer Prozess/Thread es ergattern kann
ReleaseMutex(hMutex);
}
// wenn du beliebig lange auf ein Mutex warten willst, weil du für den weiteren
// Programmablauf brauchst:
WaitForSingleObject(hMutex, INFINITE);
// .. code
ReleaseMutex(hMutex);
// wenn du das mutex gar nicht mehr brauchst:
CloseHandle(hMutex);

}

DWORD WINAPI testprozedur1(LPVOID data)
{
int i, j;
for (i=1; i<10;i++)
{
for (j=1;j<10;j++)
{
schreiben(1);
}
}
return((DWORD)data);
}

DWORD WINAPI testprozedur2(LPVOID data)
{
int i, j;
for (i=1; i<10;i++)
{
for (j=1;j<10;j++)
{
schreiben(2);
}
}
return((DWORD)data);
}

DWORD WINAPI testprozedur3(LPVOID data)
{
int i, j;
for (i=1; i<10;i++)
{
for (j=1;j<10;j++)
{
schreiben(3);
}
}
return((DWORD)data);
}

DWORD WINAPI testprozedur4(LPVOID data)
{
int i, j;
for (i=1; i<10;i++)
{
for (j=1;j<10;j++)
{
schreiben(4);
}
}
return((DWORD)data);
}

DWORD WINAPI testprozedur5(LPVOID data)
{
int i, j;
for (i=1; i<10;i++)
{
for (j=1;j<10;j++)
{
schreiben(5);
}
}
return((DWORD)data);
}


Jemand eine Idee wie ich den Mutex fixen kann, damit in der Ausgabe wirklich ...xxxooo---||| steht? Bisher hab ich maximal 2 komplette Ausgaben drin. Die anderen werden abgewiesen weil der Mutex schon existiert, denke ich mal. Dennoch hab ich keinen konkreten Plan.

del_4901
2008-07-09, 15:17:45
Die ganze Idee erfuellt keinen Sinn. Bei Mutexen gilt, wer zuerst mahlt, mahlt zuerst. Wenn du eine bestimmte Reihenfolge einhalten moechtest, dann musst du dich darum selber kuemmern.

robobimbo
2008-07-09, 15:26:13
ich würd auch sagen - der mutex gehört in der main angelegt und auch wieder gelöscht (create..., close...).

deine schreiben() funktion sollte den mutex nur benutzen (waitforsingle... release...)

und wie schon von alphatier gesagt - die reihenfolge ist nicht definiert

Gast
2008-07-10, 11:25:47
Die ganze Idee erfuellt keinen Sinn. Bei Mutexen gilt, wer zuerst mahlt, mahlt zuerst. Wenn du eine bestimmte Reihenfolge einhalten moechtest, dann musst du dich darum selber kuemmern.
Für sowas gibts den "umgedrehten Mutex" besser bekannt als Condition Variable (http://en.wikipedia.org/wiki/Condition_variable). Damit kann man auf ein Ereignis warten.