-2

I am new to multithreading, and any answers will be greatly appreciated. I am running an example from a tutorial which uses 3 threads; two created by the user, and one for main itself. Here's the code:

#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;
}

I basically want to confirm that in the for loop in main, the following statement

copy_employee(&employee_of_the_day, &eotd);

could be executed by ANY of the 3 threads; am I right? The fact that the subsequent comparisons are obviously not atomic raises some confusions. Any clarifications/corrections to this will be greatly helpful.

Incidentally, any good recommendations for tutorials on multithreading in C?

Thanks a lot!

Iceman
  • 4,202
  • 7
  • 26
  • 39

3 Answers3

3

No, the code in main is executed by only one thread.

The atomicity is ensured in copy_employee functions using mutexes.

vladmihaisima
  • 2,119
  • 16
  • 20
  • Thanks for the answer. Any ideas why the code's author ran the for loop so many times? Just to be sure, user created threads 1 and 2 run once, right? Thanks a lot! – Iceman Apr 12 '12 at 15:10
  • Yes, they run only once. There is no obvious reason in the current implementation to run that loop many times. Maybe initially copy_employee was written without the mutex and he wanted to 'test' it ? Just a theory... – vladmihaisima Apr 12 '12 at 15:15
2

I basically want to confirm that in the for loop in main, the following statement

copy_employee(&employee_of_the_day, &eotd);

could be executed by ANY of the 3 threads; am I right?

Not really, since that statement is only executed by the main thread and not by the other two threads.

Community
  • 1
  • 1
Tudor
  • 61,523
  • 12
  • 102
  • 142
2

Your main thread (and none of the worker threads) will execute everything within main() and then end. Both of your worker threads will execute everything within do_loop() and end once they leave the function.

This sounds a bit like you're confusing phtread_create() with fork(). pthread_create() will use the function provided as the entry point while fork() will start from the position it's been called.

Mario
  • 35,726
  • 5
  • 62
  • 78
  • Great. So that means that when the call to copy_employee() is made in the for loop in main, any of the two worker threads could execute that function? Thanks! – Iceman Apr 12 '12 at 15:19
  • All three threads call `copy_employee()` at some time, but with different parameters and from different positions in the code. The mutex lock ensures only one thread runs that copy code at the same time. – Mario Apr 12 '12 at 15:21
  • So just to be sure, everytime in the for loop, its the main's thread which runs copy_employee(), right? The fact that the code's author iterates for this many times was causing confusion. – Iceman Apr 12 '12 at 15:25
  • Yes, only the main thread will run the loop inside `main()`. The worker threads only run code within `do_loop()`. To me it looks like it's looping that often to give the workers enough time to so something. I wouldn't call it good design, but it's just for learning purposes anyway. If this would be some kind of real database and `main` would be meant to verify the data, it would just be an infinite loop (or till the program has to end). – Mario Apr 12 '12 at 15:32