c - 意外的 pthread 函数输出

标签 c multithreading pthreads posix

我是 C 的新手,正在学习信号量。我正在尝试使用 pthreads、mutex 和 semaphores 来实现一种复杂的用餐哲学家情境。

这个想法是一个信号量代表一台服务器,让人们坐在两张 table 上(每张 table 有 4 个位置,总共 8 个座位)。每个表也由一个计数信号量控制。每个盘子都由互斥体控制,以避免竞争条件。每个人都由一个线程表示。

我不明白为什么在我的代码中同一个顾客一直在吃,而且似乎没有增加。

代码:

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


sem_t server_sem;
int server_pshared;
int server_ret;
int server_count = 10;

sem_t tablea_sem;
int tablea_pshared;
int tablea_ret;
int tablea_count = 4;

sem_t tableb_sem;
int tableb_pshared;
int tableb_ret;
int tableb_count = 4;



//server_ret = serm_open("serverSem", O_CREAT | O_EXCL, 0644, server_count);

int customer_count = 10;
pthread_t customer[10];
//pthread_t plates[8]

int plate_count = 8;
pthread_mutex_t plates[8];


void *eat(void *i) {

    int n = *((int *) i);

    pthread_mutex_lock(&plates[n]);
    printf("Customer %d is eating\n", n);
    sleep(5);
    pthread_mutex_unlock(&plates[n]);
    printf("Customer %d is finished eating\n", n);

    return (NULL);
}

int main() {


   server_ret = sem_init(&server_sem, 1, server_count);
   tablea_ret = sem_init(&tablea_sem, 1, tablea_count);
   tableb_ret = sem_init(&tableb_sem, 1, tableb_count);

   //customer = (pthread_t[10] *)malloc(sizeof(customer));

   printf ("starting thread, semaphore is unlocked.\n");

   int i;
   int j;
   int k;




   for(i=0;i<plate_count;i++) {
      pthread_mutex_init(&plates[i],NULL);
      printf("Creating mutex for plate %d\n", i);
   }

   sem_wait(&server_sem);

   for (j=0;j<customer_count;j++) {
      //pthread_create(&customer[j],NULL,(void *)eat,&j);
      if (j<4) {
        sem_wait(&tablea_sem);
        sem_post(&tableb_sem);
        pthread_create(&customer[j],NULL,(void *)eat,&j);

        printf("Creating thread for customer %d\n", j);
      }
      else {
        sem_post(&tablea_sem);
        sem_wait(&tableb_sem);
        pthread_create(&customer[j],NULL,(void *)eat,&j);

        printf("Creating thread for customer %d\n", j);
      }

   }

   for(k=0;k<customer_count;k++) {
      pthread_join(customer[k],NULL);
      printf("Joining thread %d\n", k);
   }

   for(i=0;i<plate_count;i++) {
      pthread_mutex_destroy(&plates[i]);
   }

   return 0;
   }

控制台输出:

starting thread, semaphore is unlocked.
Creating mutex for plate 0
Creating mutex for plate 1
Creating mutex for plate 2
Creating mutex for plate 3
Creating mutex for plate 4
Creating mutex for plate 5
Creating mutex for plate 6
Creating mutex for plate 7
Creating thread for customer 0
Creating thread for customer 1
Creating thread for customer 2
Creating thread for customer 3
Creating thread for customer 4
Creating thread for customer 5
Creating thread for customer 6
Creating thread for customer 7
Creating thread for customer 8
Creating thread for customer 9
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Customer 10 is finished eating
Joining thread 0
Joining thread 1
Joining thread 2
Joining thread 3
Joining thread 4
Joining thread 5
Joining thread 6
Joining thread 7
Joining thread 8
Joining thread 9

编辑:

更新pthread_create的最后一个参数解决了customers递增的问题:

pthread_create(&customer[j],NULL,(void *)eat,(void *) (intptr_t) j);

但是,它从 6 开始,然后出现索引越界类型的问题。

现在控制台输出:

starting thread, semaphore is unlocked.
Creating mutex for plate 0
Creating mutex for plate 1
Creating mutex for plate 2
Creating mutex for plate 3
Creating mutex for plate 4
Creating mutex for plate 5
Creating mutex for plate 6
Creating mutex for plate 7
Creating thread for customer 0
Creating thread for customer 1
Creating thread for customer 2
Creating thread for customer 3
Creating thread for customer 4
Creating thread for customer 5
Creating thread for customer 6
Creating thread for customer 7
Creating thread for customer 8
Creating thread for customer 9
Customer 6 is eating
Customer 7 is eating
Illegal instruction (core dumped)

最佳答案

用线

pthread_create(&customer[j],NULL,(void *)eat,&j);

您将变量j 的地址作为参数传递给线程。并且您将相同的地址传递给相同的变量给所有线程。

当循环结束时,j 的值将等于customer_count,这就是线程可能用作数组索引的值。这是 curseo 越界导致未定义的行为

至于一个可能的解决方案,这实际上是一个接受将整数值转换为指针,然后在线程中将其转换回来的地方。不过,这必须分几步完成。首先在创建线程时:

pthread_create(&customer[j],NULL,(void *)eat, (void *) (intptr_t) j);

然后在线程本身:

int n = (int) (intptr_t) i;

关于c - 意外的 pthread 函数输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46600375/

相关文章:

c - 链表不打印?

java - 如何从 SurfaceView 正确更新 Android UI

c# System.Threading.Timer 等待处理

linux - pthread_cond_timedwait 提前一秒返回

C:获取输入并将其存储到没有任何库的字符中

c - Linux 驱动程序 try & catch

c - 绕过函数中的变量参数列表

multithreading - 我应该在UI Action 中使用后台线程吗?

c - 是否需要互斥锁来同步 pthread 之间的简单标志?

linux - 获取当前的cpu信息