Pthread 的问题;改变价值等

Problems with Pthreads; Changing value, etc

我知道标题含糊不清,我就是想不出还能叫它什么。

sleeper.h

#ifndef SLEEPER_H
#define SLEEPER_H
#include <unistd.h>

int rideTime(int, int);
void walkAroundTime(int);

#endif

sleeper.c

#include <stdio.h>
#include <stdlib.h>
#include "sleeper.h"

int rideTime(int id, int car) {

int seconds = ( rand() % 5) + 1 ;
printf ("Person %d is riding car %d for  %d seconds.\n", id, car, seconds);
sleep (seconds); 

return car;

}

void walkAroundTime(int id) {

int seconds = (rand() % 10) + 1 ;
printf ("Person %d is walking around for  %d seconds.\n", id, seconds);
sleep (seconds);

}

bumper_cars.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include "sleeper.h"

void* person(void*);
int getInLine(int);
void returnCar(int);

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t car_availability = PTHREAD_COND_INITIALIZER;
int available_cars;
int num_cars;
int* cars;

int main(int argc, char* argv[]) {
   num_cars = atoi(argv[1]);
   int num_people = atoi(argv[2]);
   int sim_time = atoi(argv[3]);

   available_cars = num_cars;
   cars = calloc(num_cars, sizeof(int));
   pthread_t* threads = calloc(num_people, sizeof(pthread_t));

    srand((unsigned)time (NULL));

   for (int i = 0; i < num_cars; i++) {
      cars[i] = 1;
   }

   for (int i = 0; i < num_people; i++) {
        int* id = malloc(sizeof(*id));
      *id = i + 1;
      pthread_create(&threads[i], NULL, person, (void*)(id));
   }

    //printf("MAIN: Sleeping for %d seconds\n", sim_time);
   sleep(sim_time);
    //printf("Done sleeping.\n");

   for (int i = 0; i < num_people; i++) {
      pthread_cancel(threads[i]);
   }

   printf("Simulation complete.\n");

   pthread_mutex_destroy(&lock);
   free(cars);
   free(threads);

   exit(EXIT_SUCCESS);
}

void* person(void* arg) {
    int car = 0;
   int id = *((int *) arg);
   while (1) {
      walkAroundTime(id);
      car = getInLine(id);
      rideTime(id, car);
      returnCar(car);
   }
}

int getInLine(int id) {
    int car = 0;

    printf("Person %d is waiting for a car.\n", id);
    pthread_mutex_lock(&lock);

    if (available_cars == 0) {
        pthread_cond_wait(&car_availability,&lock);
    }

    for (int i = 0; i < num_cars; i++) {
        if (cars[i] == 1) {
            car = i + 1;
            cars[i] = 0;
            break;
        }
    } 
    available_cars--;

    return car;
}

void returnCar(int carID) {
    available_cars++;
    cars[carID] = 1;
    printf("Car %d has been returned.\n", carID);
   pthread_cond_broadcast(&car_availability);
    pthread_mutex_unlock(&lock);
}

所以...我的程序有两个问题。最重要的是它只适用于一辆车。如果有多辆车,一辆车被拿走了,其他人还得等着还车。

第二个不太重要的问题是,当我只用 1 辆车开始代码时,汽车的 ID 从 0 开始,然后在 1 和 0 之间交替,而实际上它应该只是 1。查看我的代码,这些问题的根源对我来说并不明显......事实证明 gdb 相当无用。

问题是一旦拿到车就拿锁时间太长了。我以这种方式修改了您的功能,并在评论中注明了更改:

int getInLine(int id) {
    int car = 0;

    printf("Person %d is waiting for a car.\n", id);
    pthread_mutex_lock(&lock);

    // Use a while loop because pthread_cond_wait() is subject to
    // spurious awakenings.
    while (available_cars == 0) {
        pthread_cond_wait(&car_availability,&lock);
    }

    for (int i = 0; i < num_cars; i++) {
        if (cars[i] == 1) {
            car = i + 1;
            cars[i] = 0;
            break;
        }
    } 
    available_cars--;
    // Unlock the mutex here now that we are done acquiring the car.
    // If we don't unlock the mutex here, no one else can acquire a car.
    pthread_mutex_unlock(&lock);

    return car;
}

void returnCar(int carID) {
    // Lock the mutex here before returning the car.
    pthread_mutex_lock(&lock);
    available_cars++;
    // Need -1 here because carID is one bigger than the index.
    cars[carID-1] = 1;
    printf("Car %d has been returned.\n", carID);
    pthread_cond_broadcast(&car_availability);
    pthread_mutex_unlock(&lock);
}

顺便说一下,我注意到您使用 rand() 生成 运行dom 号码。但是,如果多个线程同时调用 rand(),您将获得相同的 运行dom 编号(至少当我 运行 您的程序时是这样)。您应该改用 rand_r() 并为每个线程创建不同的种子。