C信号量未按预期锁定

时间:2017-05-06 22:01:55

标签: c locking semaphore

我一直试图通过这个简单的售票程序来学习信号量。唯一的问题是,目前的信号量目前还没有保护<![CDATA[ 0494&#47;12 34 56 ]]> numTickets的价值。我发现这是因为有时售出的门票总数将达到51.

是否正确实现了信号量?

ticketsSold

1 个答案:

答案 0 :(得分:0)

我相信我的代码可以看到两个问题:

1)由于你正在启动多个线程(每个卖家一个线程),你应该有一个p_threads数组,而不仅仅是一个。否则,pthread_join将不会加入所有创建的线程,而只会加入最后一个(因为每次创建新线程时,都会覆盖先前创建的线程的句柄)

您的主要内容应与以下内容类似:

int main() {
  numTickets = 50;
  int numSellers = 4;
  sem_init(&mySem, 0, 1);

  pthread_t sellerThread[4];

  for (int i = 0; i < numSellers; i++) {
    pthread_create(&sellerThread[i], NULL, sell_ticket, (void *)i);
  }
  for (int i = 0; i < numSellers; i++) {
    pthread_join(sellerThread[i], NULL);
  }
  printf("All tickets sold!\n");
  return 0;
}

2)此外,就像Gene已正确评论一样,您还需要使用信号量来读取故障单数量(在ifwhile条件测试中)。否则你仍然可能会遇到一个线程正在写入,另一个正在读取的情况。

但是请注意,在整个循环持续时间内获取信号量将导致只有一个主题销售所有门票。

因此,sell_ticket函数应该类似于:

void* sell_ticket(void *sellerNum) {
  int sell = (int) sellerNum;
  int ticketsSold = 0;

  while (true) {
    // Check the number of tickets left. If sold out break out of infinite loop
    sem_wait(&mySem);
    if (numTickets <= 0) {
      sem_post(&mySem);
      break;
    }
    sem_post(&mySem);

    srand ( time(NULL) );
    int random_number = rand();
    for (int i = 1; i < random_number % 5 ; i++) {
      // Wait for semaphore before reading numTickets value in if condtion
      sem_wait(&mySem);

      if (numTickets > 0) {
        numTickets--;
        ticketsSold++;
        printf("Seller # %d  sold a ticket. Tickets left: %d\n", sell, numTickets);
      }
       // Post after if
       sem_post(&mySem);
    }
  }
  printf("Seller #%d noticed all tickets sold! (I sold %d myself) \n", sell, ticketsSold);
}