意外的数字输出

Unexpected number output

我正在尝试创建一个程序来解决使用 posix 线程的哲学家用餐问题。然而,我一开始就卡住了,因为 std :: cout << id + 1 << "PHILOSOPHER: thinking" << std :: endl; 的输出; ++我;不正确并且 id 取的值太大。请指出我的错误。

pthread_mutex_t mutexSpoon[PHILOSOPHERS];

pthread_t createThread(int number){
    pthread_t id;
    int rc = pthread_create(&id, NULL, philFunc, &number);
    if(rc){
        abort();
    }
    return id;
}

void *philFunc(void *arg){
    srand(time(0));
    int id = *(int*)arg;
    int leftSpoon = (id>0) ? id-1 : PHILOSOPHERS;
    int rightSpoon = id;
    int temp;
    int i = 0;
    while(i < 10){
        usleep((200 - 50) * ( (double)rand() / RAND_MAX ) + 50);
        std::cout << id+1 << " PHILOSOPHER: thinking" << std::endl; ++i;

    }
    return nullptr;
}

main.cpp

using namespace std;
extern pthread_mutex_t mutexSpoon[PHILOSOPHERS];

int main(){
    setlocale(LC_ALL, "rus");


    for(int i = 0; i < PHILOSOPHERS; ++i)
        pthread_mutex_init(&mutexSpoon[i], NULL);


    vector<pthread_t> vecID(PHILOSOPHERS);

    for(int i = 0; i < PHILOSOPHERS; ++i)
        vecID[i] = createThread(i);

    for(int i = 0; i < PHILOSOPHERS; ++i)
        pthread_join(vecID[i], NULL);


    for(int i = 0; i < PHILOSOPHERS; ++i)
        pthread_mutex_destroy(&mutexSpoon[i]);
    return 0;
}

线程函数使用地址作为参数,您将其作为地址传递给函数 createThread - number 的局部变量。 argument 的生命周期应该不短于 thread,所以和 mutex 完全一样。使用您的代码片段作为基础,我创建了一个解决该问题的示例:

#include <iostream>
#include <cstdlib>
#include <vector>
#include <pthread.h>
#include <unistd.h>

void *philFunc(void *arg);

#define PHILOSOPHERS 10

struct Philosopher {
    pthread_mutex_t mutexSpoon;
    pthread_t id;
    int no;
};

Philosopher philosophers[PHILOSOPHERS]  = {};

pthread_t createThread(int& number){
    pthread_t id;
    int rc = pthread_create(&id, NULL, philFunc, &number);
    if(rc){
        abort();
    }
    return id;
}

void *philFunc(void *arg){
    srand(time(0));
    int id = *(int*)arg;
    int leftSpoon = (id>0) ? id-1 : PHILOSOPHERS;
    int rightSpoon = id;
    int temp;
    int i = 0;
    while(i < 10){
        usleep((200 - 50) * ( (double)rand() / RAND_MAX ) + 50);
        std::cout << id+1 << " PHILOSOPHER: thinking" << std::endl; ++i;

    }
    return nullptr;
}

extern pthread_mutex_t mutexSpoon[PHILOSOPHERS];

int main(){
    setlocale(LC_ALL, "rus");

    for(int i = 0; i < PHILOSOPHERS; ++i) {
        pthread_mutex_init(&philosophers[i].mutexSpoon, NULL);
        philosophers[i].no = i;
        philosophers[i].id = createThread(philosophers[i].no);
    }
    
    for(int i = 0; i < PHILOSOPHERS; ++i)
        pthread_join(philosophers[i].id, NULL);


    for(int i = 0; i < PHILOSOPHERS; ++i)
        pthread_mutex_destroy(&philosophers[i].mutexSpoon);
    return 0;
}

如您所见,现在每个线程都有自己的结构 Philosopher,按应有的方式存储其数据。虽然 philosophers 这里是一个数组,但它可以是任何其他容器,只要它的元素足够长并且不会更改它们的地址(pthread mutex 的某些实现的要求)。

请注意 createThread(int& number) 现在通过引用获取其参数,因此表达式 &number 将获取实际对象位置的地址,而不是局部变量的地址。

如果使用 C++ 线程支持和 std::future,此代码会更简单。