【问题标题】:Multithreading in CC中的多线程
【发布时间】:2012-04-12 15:05:06
【问题描述】:

我是多线程的新手,任何答案都将不胜感激。我正在运行一个使用 3 个线程的教程中的示例;两个由用户创建,一个为 main 本身。代码如下:

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

我基本上是想确认在main中的for循环中,如下语句

copy_employee(&employee_of_the_day, &eotd);

可以由 3 个线程中的任何一个执行;我对吗? 随后的比较显然不是原子的,这一事实引起了一些混乱。对此的任何澄清/更正都将非常有帮助。

顺便说一句,关于 C 中的多线程教程有什么好的建议吗?

非常感谢!

【问题讨论】:

标签: c multithreading


【解决方案1】:

不,main中的代码只由一个线程执行。

使用互斥锁在 copy_employee 函数中确保原子性。

【讨论】:

  • 感谢您的回答。任何想法为什么代码的作者多次运行 for 循环?可以肯定的是,用户创建的线程 1 和 2 运行一次,对吗?非常感谢!
  • 是的,它们只运行一次。当前实现中没有明显的理由多次运行该循环。也许最初 copy_employee 是在没有互斥锁的情况下编写的,他想“测试”它?只是一个理论......
【解决方案2】:

您的主线程(并且没有任何工作线程)将执行main() 中的所有内容,然后结束。您的两个工作线程都将执行 do_loop() 内的所有内容,并在它们离开函数后结束。

这听起来有点像您将phtread_create()fork() 混淆了。 pthread_create() 将使用提供的函数作为入口点,而 fork() 将从它被调用的位置开始。

【讨论】:

  • 太棒了。所以这意味着当在 main 的 for 循环中调用 copy_employee() 时,两个工作线程中的任何一个都可以执行该函数?谢谢!
  • 所有三个线程都在某个时间调用copy_employee(),但使用不同的参数并且来自代码中的不同位置。互斥锁确保只有一个线程同时运行复制代码。
  • 所以为了确定,每次在 for 循环中,它的主线程运行 copy_employee(),对吗?代码作者多次迭代的事实引起了混乱。
  • 是的,只有主线程会在main()内部运行循环。工作线程只运行do_loop() 内的代码。对我来说,它似乎经常循环以给工人足够的时间来做某事。我不会称之为好的设计,但无论如何它只是为了学习目的。如果这将是某种真正的数据库并且main 将用于验证数据,那将只是一个无限循环(或直到程序必须结束)。
【解决方案3】:

我基本上是想确认在main中的for循环中,如下语句

copy_employee(&employee_of_the_day, &eotd);

可以由 3 个线程中的任何一个执行;我说的对吗?

并非如此,因为该语句仅由主线程执行,而不由其他两个线程执行。

【讨论】:

    猜你喜欢
    • 2010-12-14
    • 1970-01-01
    • 2011-06-02
    • 2016-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多