简体   繁体   English

意外的pthread函数输出

[英]Unexpected pthread function output

I'm new to C and learning about semaphores. 我是C语言的新手,正在学习信号量。 I'm trying to implement a sort of complex dining philosophers situation using pthreads, mutex, and semaphores. 我正在尝试使用pthreads,mutex和semaphores实现某种复杂的餐饮哲学家的情况。

The idea is that one semaphore, representing a server, seats people at two tables (4 places each, 8 total). 这个想法是,一个代表服务器的信号灯可将人们坐在两张桌子上(每张桌子有4个席位,共8个席位)。 Each table is also controlled by a counting semaphore. 每个表还由计数信号量控制。 Each plate is controlled by a mutex to avoid race conditions. 每个板块均由互斥锁控制,以免出现竞争状况。 Each person is represented by a thread. 每个人都由一个线程代表。

I cannot see why in my code the same customer keeps eating, and does not seem to increment. 我看不出为什么在我的代码中,同一位客户不断进餐,而且似乎没有增加。

Code: 码:

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

Console output: 控制台输出:

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

EDIT: 编辑:

Updating the last parameter of pthread_create solves the issue of customers incrementing : 更新pthread_create的最后一个参数解决了客户增加的问题:

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

However, it starts at 6, and then there's index out of bounds type of issue. 但是,它从6开始,然后是索引超出范围的问题。

Console output now: 现在控制台输出:

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)

With the line 用线

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

you pass the address of the variable j to the thread as argument. 您将变量j的地址作为参数传递给线程。 And you pass the same address to the same variable to all threads. 然后,您将相同的地址传递给所有线程的相同变量。

When the loop is over, the value of j will be equal to customer_count and that's what the threads might use as index into the array. 循环结束后, j的值将等于customer_count ,这就是线程可能用作数组索引的内容。 And it's of curseo out of bounds leading to undefined behavior . 而且它的诅咒超出范围导致未定义的行为

As for a possible solution, this is actually one place where it's accepted to cast an integer value into a pointer, and then in the thread cast it back. 对于一种可能的解决方案,实际上是在一个地方将整数值转换为指针,然后在线程中将其转换回来。 This has to be done in a couple of steps though. 但是,这必须分两步完成。 First when creating the thread: 首先创建线程:

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

Then in the thread itself: 然后在线程本身中:

int n = (int) (intptr_t) i;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM