C信号量未按预期锁定

C信号量未按预期锁定,c,locking,semaphore,C,Locking,Semaphore,我一直在尝试通过这个简单的售票程序学习信号灯。唯一的问题是,当前使用的信号量没有保护numTickets和ticketssell的值。我发现了这一点,因为有时售出的门票总数将达到51张 是信号量的正确实现吗? #include <semaphore.h> #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <time.h> int numTicket

我一直在尝试通过这个简单的售票程序学习信号灯。唯一的问题是,当前使用的信号量没有保护
numTickets
ticketssell
的值。我发现了这一点,因为有时售出的门票总数将达到51张

是信号量的正确实现吗?

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

int numTickets;
sem_t mySem;

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

  while (numTickets > 0) {
    srand ( time(NULL) );
    int random_number = rand();
    for (int i = 1; i < random_number % 5 ; i++) {
      if (numTickets > 0) {
        sem_wait(&mySem);
        numTickets--;
        ticketsSold++;
        printf("Seller # %d  sold a ticket. Tickets left: %d\n", sell, numTickets);
        sem_post(&mySem);
      }
    }
  }
  printf("Seller #%d noticed all tickets sold! (I sold %d myself) \n", sell, ticketsSold);
}

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

  pthread_t sellerThread;

  for (int i = 0; i < numSellers; i++) {
    pthread_create(&sellerThread, NULL, sell_ticket, (void *)i);
  }
  for (int i = 0; i < numSellers; i++) {
    pthread_join(sellerThread, NULL);
  }
  printf("All tickets sold!\n");
  return 0;
}
#包括
#包括
#包括
#包括
#包括
国际货币基金组织;
sem_t mySem;
作废*卖出票(作废*卖出票){
int sell=(int)sellerNum;
int ticketssell=0;
而(numTickets>0){
srand(时间(空));
int random_number=rand();
对于(int i=1;i<随机数%5;i++){
如果(numTickets>0){
sem_wait(&mySem);
numTickets——;
票务销售++;
printf(“卖家#%d卖出了一张票。剩下的票:%d\n”,卖出,numTickets);
sem_post&mySem;
}
}
}
printf(“卖家#%d注意到所有的票都卖了!(我自己也卖了%d)”,sell,ticketssell);
}
int main(){
numTickets=50;
整数=4;
sem_init(&mySem,0,1);
pthread\u t sellerThread;
对于(int i=0;i
我相信我可以看到您的代码存在两个问题:

1) 因为您要启动多个线程(每个卖家一个线程),所以您应该有一个p_线程数组,而不仅仅是一个线程。否则,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;
}

我不是什么pthreads专家,但是当另一个线程正在编写numTickets时,我认为读取numTickets(在
if
while
中)是个问题。您需要在受信号量保护的块内获取读-修改-写序列。遗憾的是,经过各种测试,我得到了51的值。我已经看完了你的答案,现在我明白了在if和while周围放置信号量是多么明智的选择。遗憾的是,即使提供了代码。我偶尔会得到高于50的值。
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);
}