用餐哲学家的错误

时间:2017-03-21 04:34:17

标签: c

我在Ubuntu上运行算法时有点头疼。它似乎在Windows上运行得很好(Dev C ++或CodeBlocks),但当我尝试在Geany上运行它时,我一直收到错误:

Filosofos.cpp:144:11: error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’ [-fpermissive]

它突出显示该区域为错误:

iret1 = pthread_create(&thread1, NULL, (void *)philosopher, (int*)p[1]);

根据我的研究,我尝试更改为long intlong long - 但没有成功。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <string.h>
#include <ctype.h>
#include <semaphore.h>

#define N 5  /* amount of philosophers*/
#define LEFT (i+N-1)%N/* left neighbor i */
#define RIGHT (i+1)%N   /* right neighbor i */
#define THINKING 0 /*  philosopher thinking */
#define HUNGRY 1 /* philosopher tries to catch the fork */
#define EATING 2 /* philosopher eating */
#define TRUE 1

sem_t s[N];                 //one semaphore for each philosopher
sem_t mutex;
int   state[N];
//array to control philosophers state
pthread_t thread1, thread2, thread3, thread4, thread5;
//one thread for each philosopher
void take_forks(int i);
void put_forks(int i);
void test(int i);
void think(int i);
void eat(int i);

/* i: number of the philosopher, from 0 to N-1 */
void philosopher(int i) {
    while (TRUE) {
        think(i);  /
        take_forks(i); /* take two forks or block it */
        eat(i);
        put_forks(i);
    }
}

void take_forks(int i) {
    sem_wait(&mutex); //down(&mutex); /* entra na regiao cri­tica */
    state[i] = HUNGRY; /* change the state to hungry */
    printf("philosopher %d HUNGRY\n",i);
    test(i);  /* try to catch two forks */
    sem_post (&mutex); // up(&mutex);  /* get out the critical region*/
    sem_wait(&s[i]); // down(&s[i]); /* block if the forks are not available */
}

void put_forks(int i) {
    sem_wait(&mutex); // down(&mutex); /* get in the critical region */
    state[i] = THINKING; /* Philosopher has ended eating  */
    printf("philosopher %d THINKING\n",i);
    test(LEFT);  /* check if the left neighbor can eat now */
    test(RIGHT); /* check if the right neighbor can eat now */
    sem_post(&mutex); // up(&mutex);  /* get out of the critical region*/
}

void test(int i) {  //test if the philosopher´s neighbors can eat
    if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) {
        state[i] = EATING;
        printf("philosopher %d EATING\n",i);
        sem_post(&s[i]); //up(&s[i]);
    }
}

void think(int i) {
    sleep(rand() % 10 + 1);
    return;
}

void eat(int i) {
    sleep(rand() % 10 + 1);
    return;
}

////////////// MAIN FUNCTION////////////////////////
int main (int argc, char *argv[])
{
    int iret1, iret2, iret3, iret4, iret5;
    int i;
    int p[N] ;

    int sem_init(sem_t *sem, int pshared, unsigned int value);

    for (i= 0; i < N ;i++ ) {
        sem_init(&s[i], 0, 1);
        p[i] = i;
    }
    sem_init(&mutex, 0, 1);

    iret1 = pthread_create(&thread1, NULL, (void *) philosopher, (int *) p[1]);
    iret2 = pthread_create(&thread2, NULL, (void *) philosopher, (int *) p[2]);
    iret3 = pthread_create(&thread3, NULL, (void *) philosopher, (int *) p[3]);
    iret4 = pthread_create(&thread4, NULL, (void *) philosopher, (int *) p[4]);
    iret5 = pthread_create(&thread5, NULL, (void *) philosopher, (int *) p[0]);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    pthread_join(thread4, NULL);
    pthread_join(thread5, NULL);

    exit(0);
}

1 个答案:

答案 0 :(得分:4)

线程启动功能的类型应为

void *(*)(void *);

所以,philosopher()需要更改为

void *philosopher(void *data)
{
    int i = *(int *) data;
    // The rest of the function
}

然后在main()

for (int i = 0; i < N; ++i) {
    pthread_create(&thread[i], NULL, philosopher, &p[i]);
}

for循环在这里是为了避免重复相同的代码,坚持DRY原则,因为如果你不这样做,那么维护你的代码将变得不可能。

这是您的代码,但已修复和改进,特别是可读性。我希望更多的程序员重视可读性,因为阅读代码是我们最常做的,我们阅读的内容比编写的要多得多

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

#define N 5                  /* amount of philosophers              */
#define LEFT (i + N - 1) % N /* left neighbor i                     */
#define RIGHT (i + 1) % N    /* right neighbor i                    */
#define THINKING 0           /*  philosopher thinking               */
#define HUNGRY 1             /* philosopher tries to catch the fork */
#define EATING 2             /* philosopher eating                  */
#define TRUE 1

sem_t s[N];                 // one semaphore for each philosopher
sem_t mutex;
int state[N];

void take_forks(int i);
void put_forks(int i);
void test(int i);
void think(int i);
void eat(int i);

void *
philosopher(void *data) 
{
    int i = *(int *) data;
    while (TRUE) {
        think(i);
        take_forks(i); /* take two forks or block it */
        eat(i);
        put_forks(i);
    }
}

void
take_forks(int i) 
{
    sem_wait(&mutex);

    state[i] = HUNGRY;
    printf("philosopher %d HUNGRY\n", i);

    test(i);  /* try to catch two forks */

    sem_post (&mutex);
    sem_wait(&s[i]);
}

void 
put_forks(int i)
{
    sem_wait(&mutex);

    state[i] = THINKING;
    printf("philosopher %d THINKING\n", i);

    test(LEFT);  /* check if the left neighbor can eat now */
    test(RIGHT); /* check if the right neighbor can eat now */

    sem_post(&mutex);
}

void 
test(int i)
{
    if ((state[i] == HUNGRY) && (state[LEFT] != EATING) && (state[RIGHT] != EATING)) {
        state[i] = EATING;
        printf("philosopher %d EATING\n", i);
        sem_post(&s[i]);
    }
}

void 
think(int i) 
{
    sleep(rand() % 10 + 1);
    return;
}

void 
eat(int i) 
{
    sleep(rand() % 10 + 1);
    return;
}

int
main(int argc, char *argv[])
{
    int i;
    pthread_t thread[N];
    int p[N];

    int sem_init(sem_t *sem, int pshared, unsigned int value);

    for (i= 0; i < N ;i++ ) {
        sem_init(&s[i], 0, 1);
        p[i] = i;
    }
    sem_init(&mutex, 0, 1);

    for (int i = 0; i < N; ++i)
        pthread_create(&thread[i], NULL, philosopher, &p[i]);
    for (int i = 0; i < N; ++i)
        pthread_join(thread[i], NULL);

    return 0;
}

不要使用评论,说出像

这样非常明确的内容
state = NEW_STATE; // Change the state to NEW_STATE