我知道标题含糊不清,我只是无法弄清楚还有什么可以称之为。
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被证明是无益的。
答案 0 :(得分:1)
问题在于,一旦获得锁定以获得汽车,您将持有锁太长时间。我以这种方式修改了您的功能,注释中注明了更改:
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()
生成随机数。但是,如果多个线程同时调用rand()
,您将获得相同的随机数(至少是我运行程序时发生的情况)。您应该使用rand_r()
代替并为每个线程创建不同的种子。