2012-04-12 11 views
-2

Ich bin neu im Multithreading, und jede Antwort wird sehr geschätzt. Ich führe ein Beispiel aus einem Tutorial, das 3 Threads verwendet; zwei vom Benutzer erstellt und einer für die Hauptbenutzer. Hier ist der Code:Multithreading in C

#include <stdio.h> 
#include <pthread.h> 
#include <string.h> 
#include <stdlib.h> 

#define NUM_EMPLOYEES 2 

/* global mutex for our program. assignment initializes it */ 
pthread_mutex_t a_mutex = PTHREAD_MUTEX_INITIALIZER; 

struct employee { 
    int number; 
    int id; 
    char first_name[20]; 
    char last_name[30]; 
    char department[30]; 
    int room_number; 
}; 

/* global variable - our employees array, with 2 employees */ 
struct employee employees[] = { 
     {1, 12345678, "danny", "cohen", "Accounting", 101}, 
     {2, 87654321, "moshe", "levy", "Programmers", 202} 
}; 

/* global variable - employee of the day */ 
struct employee employee_of_the_day; 

void copy_employee(struct employee *from, struct employee *to) { 
    int rc;  /* contain mutex lock/unlock results */ 

    /*lock the mutex, to assure exclusive access to 'a' and 'b' */ 
    rc = pthread_mutex_lock(&a_mutex); 

    to->number = from->number; 
    to->id = from->id; 
    strcpy(to->first_name, from->first_name); 
    strcpy(to->last_name, from->last_name); 
    strcpy(to->department, from->department); 
    to->room_number = from->room_number; 

    /* unlock mutex */ 
    rc = pthread_mutex_unlock(&a_mutex); 
} 

/* function to be executed by the variable setting threads thread */ 
void *do_loop(void *data) { 
    int my_num = *((int*)data); 

    while(1) { 
     /* set employee of the day to be the one with number 'my_num' */ 
     copy_employee(&employees[my_num-1], &employee_of_the_day); 
    } 
} 

/* program's execution begins in main */ 

int main(int argc, char *argv[]) { 
    int i; 
    int thr_id1; 
    int thr_id2; 
    pthread_t p_thread1; 
    pthread_t p_thread2; 
    int num1 = 1; 
    int num2 = 2; 
    struct employee eotd; 
    struct employee *worker; 

    /* initialize employee of the day to first 1 */ 
    copy_employee(&employees[0], &employee_of_the_day); 

    /* create a new thread that will execute 'do_loop()' with '1' */ 
    thr_id1 = pthread_create(&p_thread1, NULL, do_loop, (void*)&num1); 

    /* create a new thread that will execute 'do_loop()' with '2' */ 
    thr_id2 = pthread_create(&p_thread2, NULL, do_loop, (void*)&num2); 

    /* run a loop that verifies integrity of 'employee of the day' many */ 
    /* many times.... */ 
    for (i = 0; i < 600000; i++) { 
     /* save contents of 'employee of the day' to local 'worker' */ 
     copy_employee(&employee_of_the_day, &eotd); 
     worker = &employees[eotd.number-1]; 

     /* compare employees */ 
     if (eotd.id != worker->id) { 
      printf("mismatching 'id', %d != %d (loop '%d')\n", 
        eotd.id, worker->id, i); 
      exit(0); 
     } 
     if (strcmp(eotd.first_name, worker->first_name) != 0) { 
      printf("mismatching 'first_name' , %s != %s (loop '%d')\n", 
        eotd.first_name, worker->first_name, i); 
      exit(0); 
     } 
     if (strcmp(eotd.last_name, worker->last_name) != 0) { 
      printf("mismatching 'last_name' , %s != %s (loop '%d')\n", 
        eotd.last_name, worker->last_name, i); 
      exit(0); 
     } 
     if (strcmp(eotd.department, worker->department) != 0) { 
      printf("mismatching 'department' , %s != %s (loop '%d')\n", 
        eotd.department, worker->department, i); 
      exit(0); 
     } 
     if (eotd.room_number != worker->room_number) { 
      printf("mismatching 'room_number' , %d != %d (loop '%d')\n", 
        eotd.room_number, worker->room_number, i); 
      exit(0); 
     } 
    } 

    printf("Glory, employees contents was always consistent\n"); 
    return 0; 
} 

ich im Grunde, dass in der for-Schleife in Haupt bestätigen möchten, die folgende Anweisung

copy_employee(&employee_of_the_day, &eotd); 

konnte von keinem der drei Threads ausgeführt werden; habe ich recht? Die Tatsache, dass die nachfolgenden Vergleiche offensichtlich nicht atomar sind, wirft einige Verwirrungen auf. Etwaige Klarstellungen/Korrekturen werden sehr hilfreich sein.

Übrigens, irgendwelche guten Empfehlungen für Tutorials zum Multithreading in C?

Vielen Dank!

Antwort

2

Ihr Haupt-Thread (und keiner der Worker-Threads) wird alles innerhalb main() ausführen und dann enden. Beide Worker-Threads führen alles innerhalb von do_loop() aus und enden, sobald sie die Funktion verlassen.

Das klingt ein bisschen wie Sie sind verwirrend phtread_create() mit fork(). pthread_create() verwendet die Funktion als Einstiegspunkt, während fork() von der Position aus beginnt, an der es aufgerufen wurde.

+0

Großartig. Das heißt also, wenn der Aufruf von copy_employee() in der for-Schleife in main erfolgt, könnte jeder der beiden Worker-Threads diese Funktion ausführen? Vielen Dank! – Iceman

+0

Alle drei Threads rufen 'copy_employee()' zu einem bestimmten Zeitpunkt auf, aber mit unterschiedlichen Parametern und von verschiedenen Positionen im Code. Die Mutex-Sperre stellt sicher, dass nur ein Thread diesen Code zur gleichen Zeit ausführt. – Mario

+0

Also nur um sicher zu sein, jedes Mal in der for-Schleife, es ist der Haupt-Thread, der copy_employee() läuft, oder? Die Tatsache, dass der Autor des Codes viele Male iterierte, verursachte Verwirrung. – Iceman

3

Nein, der Code in main wird nur von einem Thread ausgeführt.

Die Atomarität wird in copy_employee-Funktionen mithilfe von Mutexes sichergestellt.

+0

Danke für die Antwort. Irgendwelche Ideen, warum der Autor des Codes die for-Schleife so oft ausgeführt hat? Nur um sicher zu sein, Benutzer erstellt Threads 1 und 2 einmal ausgeführt, oder? Danke vielmals! – Iceman

+0

Ja, sie laufen nur einmal. Es gibt keinen offensichtlichen Grund in der aktuellen Implementierung, diese Schleife viele Male auszuführen. Vielleicht wurde copy_employee zunächst ohne den Mutex geschrieben und er wollte es "testen"? Nur eine Theorie ... – vladmihaisima

+0

Könnte der Grund sein. – Iceman

2

ich im Grunde, dass in der for-Schleife in Haupt, die folgende Aussage

copy_employee (& employee_of_the_day, & EOTD) bestätigen möchten;

könnte von jedem der 3 Threads ausgeführt werden; habe ich recht?

Nicht wirklich, da diese Anweisung nur vom Haupt-Thread und nicht von den anderen beiden Threads ausgeführt wird.