pthread_create

时间:2018-03-28 01:53:13

标签: c linux multithreading pthreads

我遇到以下C代码的问题。代码本身应该创建5个线程来模拟线程正在访问共享数据的Dining Philosophers问题。代码如下:

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

//creation of the mutex lock, condition variables, and state
pthread_mutex_t mutex;
pthread_cond_t cond_var[5];
enum{THINKING, HUNGRY, EATING}state[5];

//test if possible to get forks
void test(int pNumber){

    //start eating if the adjacent philosophers aren't eating
    if((state[(pNumber + 1) % 5] != EATING) && (state[(pNumber + 4) % 5] != EATING)){
        state[pNumber] = EATING;

        //signal self if test() called by another thread
        pthread_cond_signal(&cond_var[pNumber]);
    }
}

//used to make the philosopher's forks unavailable
void pickup_forks(int pNumber){

    //get lock
    pthread_mutex_lock(&mutex);

    //set state to hungry
    state[pNumber] = HUNGRY;
    printf("Philosopher %d is HUNGRY\n", pNumber);

    //attempt to begin eating. if unable to, will wait
    test(pNumber);
    while(state[pNumber] != EATING){
        pthread_cond_wait(&cond_var[pNumber], &mutex);
        //switched the order of the arguments
    }

    //release lock
    pthread_mutex_unlock(&mutex);
}

//allow neighbors to use philosopher's forks
void release_forks(int pNumber){

    //get lock
    pthread_mutex_lock(&mutex);

    //set own state to thinking
    state[pNumber] = THINKING;

    //tell adjacent philosophers to try to eat
    test(((pNumber + 1) % 5)); 
    test(((pNumber + 4) % 5));

    //release lock
    pthread_mutex_unlock(&mutex);
}

//used by the thread to run the philosophers
void *runPhilosopher(void *x){

    //which philosopher it is
    int pNumber = *((int*) x);

    //initially thinking
    state[pNumber] = THINKING;
    printf("Philosopher %d is THINKING\n", pNumber);

    //"think" for a random amount of time between 1-3 seconds
    int sleepTime = rand() % 3 + 1;
    sleep(sleepTime);

    //each philosopher eats a total of 5 times
    int i = 0;
    for(i = 0; i < 5; i++){

        //get the forks and begin eating
        pickup_forks(pNumber);

        //eating time
        sleep(2);

        //put down forks and resume thinking
        release_forks(pNumber);
        sleepTime = rand() % 3 + 1;
        sleep(sleepTime);
    }

    printf("Philosopher %d has finished eating\n", pNumber);
}

int main(int argc, char *argv[])
{

    pthread_mutex_init(&mutex, NULL);

    int i = 0;
    for(i = 0; i < 5; i++){
        pthread_cond_init(&cond_var[i], NULL);
    }


    pthread_t tid[5];    //thread id
    pthread_attr_t attr;     //set of thread attributes

    pthread_create(&tid[0], NULL, runPhilosopher, (void *) 0);
    pthread_create(&tid[1], NULL, runPhilosopher, (void *) 1);
    pthread_create(&tid[2], NULL, runPhilosopher, (void *) 2);
    pthread_create(&tid[3], NULL, runPhilosopher, (void *) 3);
    pthread_create(&tid[4], NULL, runPhilosopher, (void *) 4);

    //wait for threads to finish
    for(i = 0; i < 5; i++){
        pthread_join(tid[i], NULL);
    }

    return 0;
}

我使用gedit在Linux虚拟机上。该程序编译正常,但在尝试运行它时,我得到一个“分段错误”错误,这是来自尝试的线程创建,根据gdb。我发现这里没有任何相关问题适用于我的程序。

我尝试过的事情:

  • 评论绝大多数代码并尝试创建一个简单运行runPhilosopher的单个线程,该线程已被剥离为仅一个printf语句。这导致代码似乎没有创建线程,因为没有输出。
  • 使用&amp; attr替换线程创建中的NULL。这将错误更改为Aborted,但没有做任何其他操作。
  • 对所有这些使用单个线程ID,就像我在之前的程序中一样。这没什么区别。
  • 我不记得的其他一些可能性

有人看到一个我忽略的简单解决方案,还是我的程序存在严重缺陷?我无法理解这个问题是什么,但我完全承认我不熟悉C.任何帮助都将不胜感激!

1 个答案:

答案 0 :(得分:4)

你的问题在这里:

int pNumber = *((int*) x);

当你调用pthread_create()时,你会将一个整数强制转换为指针,然后你将它转换为线程函数中的指针并继续取消引用它。

相反,请尝试

    int pNumber = (int) x;

请注意,这可能会导致编译器警告sizeof(int) != sizeof(void*)。您可能希望先转换为uintptr_t

或者,您可以将int存储在本地变量中,并将其地址传递给pthread_create。只需确保在包含函数返回之前所有线程都已停止。

或者,您可以mallocint作为成员的结构,并将指针传递给它。