2012-04-12 95 views
-2

我是多線程新手,任何答案都將不勝感激。我正在運行一個使用3個線程的教程的例子;兩個由用戶創建,另一個用於主體本身。下面的代碼:多線程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; 
} 

我基本上要確認的是,在for循環爲主,下面的語句

copy_employee(&employee_of_the_day, &eotd); 

可以由任何3個線程的執行;我對嗎? 事實上,隨後的比較顯然不是原子提出了一些混淆。對此的任何澄清/更正將大有幫助。

順便說一句,任何有關C多線程教程的良好建議?

非常感謝!

回答

2

您的主線程(並且沒有工作線程)將執行main()中的所有內容,然後結束。兩個工作線程將執行do_loop()中的所有內容,並在離開該函數後結束。

這聽起來有點像你混淆phtread_create()fork()pthread_create()將使用提供的功能作爲入口點,而fork()將從其被調用的位置開始。

+0

太好了。所以這意味着當在main中for循環中調用copy_employee()時,兩個工作線程中的任何一個都可以執行該函數?謝謝! – Iceman 2012-04-12 15:19:28

+0

所有這三個線程都會在某個時間調用'copy_employee()',但使用不同的參數和代碼中的不同位置。互斥鎖確保只有一個線程同時複製代碼。 – Mario 2012-04-12 15:21:20

+0

所以可以肯定的是,每次在for循環中,其主線程運行copy_employee(),對吧?代碼作者多次迭代的事實引起了混淆。 – Iceman 2012-04-12 15:25:36

3

不,主代碼僅由一個線程執行。

在使用互斥鎖的copy_employee函數中確保原子性。

+0

感謝您的回答。爲什麼代碼的作者爲何多次運行for循環?可以肯定的是,用戶創建的線程1和2運行一次,對吧?非常感謝! – Iceman 2012-04-12 15:10:47

+0

是的,他們只運行一次。在當前的實現中沒有明顯的原因多次運行該循環。也許最初copy_employee是沒有互斥體編寫的,他想'測試'它?只是一個理論... – vladmihaisima 2012-04-12 15:15:14

+0

可能是原因。 – Iceman 2012-04-12 15:26:34

2

我基本上要確認的是,在對主,下面的語句

copy_employee(& employee_of_the_day,& EOTD)循環;

可以由3個線程中的任何一個執行;我對嗎?

不是真的,因爲該語句只能由主線程執行,而不能由其他兩個線程執行。