AlSvartr
2005-11-18, 14:24:59
Ich habe zu folgendem Code eine kleine Frage (ist mein erster Versuch mit Threads). Und zwar gehts mir darum, ob es denn ueberhaupt notwendig ist, die Threads auch noch "quasi-zusaetzlich" ueber die Konstanten bzw. currentOp zu synchronisieren, so dass auch nie was passieren kann, was nicht vorgesehen ist. Ich habs auch ohne diese Variante probiert und es funktionierte auch, aber dann stellte ich mir die Frage, ob es nicht doch passieren kann, dass der zweite Thread quasi zu frueh den Mutex lockt und konvertiert, ohne dass der erste eingelesen hat oder aehnliches. Oder ist das ausgeschlossen?
Zur Erklaerung: Ist ne kleine Uebungsaufgabe gewesen, der erste Thread soll ne Zeichenkette auslesen, der zweite Thread soll sie in Großbuchstaben konvertieren und ausgeben. Also fange ich an, indem ich mit dem ersten Thread den Mutex locke, in input einlese, den Mutex unlocke, im zweiten Thread locke, konvertiere, waehrend der erste Thread dann wartet, bis der Mutex wieder frei ist. Nach der Konvertierung erfolgt dann der Unlock seitens des zweiten Threads, womit der erste wieder lockt, die Ausgabe macht und dann wieder ne neue Zeichenkette einliest (trylock hab ich deswegen verwendet, weil ich so eben auf das unlocken zum Ende des ersten Threads verzichten kann..wenn ich da allerdings unlocken wuerde, wuerde ja wieder der zweite Thread loslegen, was die "zusaetzliche" Synchronisierung ueber mein currentOp etwas sinnvoller erscheinen laesst. Ratschlaege erwuenscht ;)
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;
char input[31];
int currentOp;
const int READ_STRING=1;
const int CONVERT_STRING=2;
const int PRINT_STRING=3;
void *readinput () {
do {
pthread_mutex_lock(&mutex); /* Trylock, weil sonst Block ab zweitem Durchlauf */
if (currentOp==READ_STRING) {
printf("Enter String: ");
fgets(input,31,stdin);
currentOp=CONVERT_STRING;
}
pthread_mutex_unlock(&mutex); /* Unlock -> Konvertierung kann in zweitem Thread erfolgen */
pthread_mutex_lock(&mutex); /* Lock fuer Ausgabe und erneutes Einlesen */
if (currentOp==PRINT_STRING) {
printf("%s\n",input);
currentOp=READ_STRING;
}
pthread_mutex_unlock(&mutex);
} while (1);
}
void *convert () {
do {
pthread_mutex_lock(&mutex); /* Lock fuer Konvertierung */
if (currentOp==CONVERT_STRING) {
int i;
for (i=0;i<strlen(input);i++) {
if (islower(input[i]))
input[i]=toupper(input[i]);
printf("%d Zeichen konvertiert\r",i+1);
}
printf("\n");
for (i=0;i<5;i++) {
printf("Warte 5 Sekunden: %d\r",i);
fflush(stdout);
sleep(1);
}
printf("Warte 5 Sekunden: 5\n");
currentOp=PRINT_STRING;
}
pthread_mutex_unlock(&mutex); /* Unlock nach Konvertierung und sleep */
} while (1);
}
int main () {
currentOp=1;
pthread_t p1,p2;
pthread_mutex_init(&mutex,NULL);
pthread_create(&p1,NULL,readinput,NULL);
pthread_create(&p2,NULL,convert,NULL);
pthread_join(p1,NULL);
pthread_join(p2,NULL);
printf("\n");
return 0;
}
Zur Erklaerung: Ist ne kleine Uebungsaufgabe gewesen, der erste Thread soll ne Zeichenkette auslesen, der zweite Thread soll sie in Großbuchstaben konvertieren und ausgeben. Also fange ich an, indem ich mit dem ersten Thread den Mutex locke, in input einlese, den Mutex unlocke, im zweiten Thread locke, konvertiere, waehrend der erste Thread dann wartet, bis der Mutex wieder frei ist. Nach der Konvertierung erfolgt dann der Unlock seitens des zweiten Threads, womit der erste wieder lockt, die Ausgabe macht und dann wieder ne neue Zeichenkette einliest (trylock hab ich deswegen verwendet, weil ich so eben auf das unlocken zum Ende des ersten Threads verzichten kann..wenn ich da allerdings unlocken wuerde, wuerde ja wieder der zweite Thread loslegen, was die "zusaetzliche" Synchronisierung ueber mein currentOp etwas sinnvoller erscheinen laesst. Ratschlaege erwuenscht ;)
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;
char input[31];
int currentOp;
const int READ_STRING=1;
const int CONVERT_STRING=2;
const int PRINT_STRING=3;
void *readinput () {
do {
pthread_mutex_lock(&mutex); /* Trylock, weil sonst Block ab zweitem Durchlauf */
if (currentOp==READ_STRING) {
printf("Enter String: ");
fgets(input,31,stdin);
currentOp=CONVERT_STRING;
}
pthread_mutex_unlock(&mutex); /* Unlock -> Konvertierung kann in zweitem Thread erfolgen */
pthread_mutex_lock(&mutex); /* Lock fuer Ausgabe und erneutes Einlesen */
if (currentOp==PRINT_STRING) {
printf("%s\n",input);
currentOp=READ_STRING;
}
pthread_mutex_unlock(&mutex);
} while (1);
}
void *convert () {
do {
pthread_mutex_lock(&mutex); /* Lock fuer Konvertierung */
if (currentOp==CONVERT_STRING) {
int i;
for (i=0;i<strlen(input);i++) {
if (islower(input[i]))
input[i]=toupper(input[i]);
printf("%d Zeichen konvertiert\r",i+1);
}
printf("\n");
for (i=0;i<5;i++) {
printf("Warte 5 Sekunden: %d\r",i);
fflush(stdout);
sleep(1);
}
printf("Warte 5 Sekunden: 5\n");
currentOp=PRINT_STRING;
}
pthread_mutex_unlock(&mutex); /* Unlock nach Konvertierung und sleep */
} while (1);
}
int main () {
currentOp=1;
pthread_t p1,p2;
pthread_mutex_init(&mutex,NULL);
pthread_create(&p1,NULL,readinput,NULL);
pthread_create(&p2,NULL,convert,NULL);
pthread_join(p1,NULL);
pthread_join(p2,NULL);
printf("\n");
return 0;
}