我如何避免偶尔的死锁? (过山车多线程)

时间:2018-04-25 06:23:11

标签: c multithreading concurrency deadlock

  

着名的过山车问题。假设有n名乘客和   一辆过山车。乘客反复等待乘车   在车上。该车具有C座的容量,C <100。 ñ,但是   cheapskate车主不会让汽车离开车站直到它   充分。编写程序来模拟此问题的解决方案。每   乘客必须是一个等待乘坐的线程,等待直到   骑行完成,从骑行出发并离开。

     

汽车应该是等待C乘客进入汽车的线程   骑车,然后绕轨道走一段固定的时间   (一些固定的睡眠时间),然后让乘客下船。确实如此   直到没有更多的乘客想要乘坐。

     

你的main()线程将在汽车线程上执行pthread_join()。   当没有更多等待的乘客线程时,汽车线程退出   因此main()线程将打印信息并退出。

     

因此,假设汽车和每位乘客都是分开的   线程。你会如何编写一个可以模拟这个系统的程序   并满足以下要求:

     
      
  1. 汽车总是乘坐C乘客;

  2.   
  3. 汽车行驶时,没有乘客会从车上跳下来;

  4.   
  5. 汽车行驶时,没有乘客会跳上车;

  6.         

    线程将通过“监视器”进行同步(记住,它   使用互斥锁和条件变量来保证互斥   它有三个操作:takeRide,loadCustomers和   unloadCustomers。第一次行动由乘客召集;一个电话   在乘客乘坐并准备好之前不会返回   离开。最后两个操作由汽车线程调用。你可以   添加任何其他内容以帮助您的设计工作。

我的问题:这些是要传递给线程的函数。 takeRide传递给乘客线程,加载和卸载传递到汽车线程。首先,乘客和汽车容量的组合是行不通的。例如,汽车和7名乘客的容量为2。这将被困在最后一位乘客身上。其次,unboarding不能正常工作。我没有看到“乘客x左车”。我如何解决这个问题并不适用于每个乘客/容量组合?我需要另一个mutex吗?另外,为什么它会像下面的示例输出一样随机停止运行?为什么carUnload无法正常工作?

示例死锁输出:容量= 2,乘客= 6

Passenger 5 is waiting for car.
Passenger 4 is waiting for car.
Passenger 3 is waiting for car.
Passenger 2 is waiting for car.
Passenger 1 is waiting for car.
Passenger 0 is waiting for car.
Car is waiting for passengers.
Passenger 4 will take ride in the car
Passenger 3 will take ride in the car
Passenger 2 is waiting for car.
Passenger 1 is waiting for car.
Passenger 5 is waiting for car.
Passenger 0 is waiting for car.

·H

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

int cap, numPass;
int passengersInCar;
bool carIsWaiting; //true if car is waiting for passengers

pthread_mutex_t rollerCoasterLock;
pthread_cond_t carLoad;
pthread_cond_t carUnload;
pthread_cond_t carFull;

.C

void takeRide(const int passenger_id);
void load();
void unload();

 void takeRide(const int passenger_id){
  pthread_mutex_lock(&rollerCoasterLock);
  while(!carIsWaiting || passengersInCar==cap){
    printf("Passenger %d is waiting for car.\n", passenger_id);
    pthread_cond_wait(&carLoad, &rollerCoasterLock);
  }
  // numPass--;
  passengersInCar++;
  printf("Passenger %d will take ride in the car\n", passenger_id);
  if (passengersInCar == cap){
    pthread_cond_broadcast(&carFull);
    // passengersInCar=0;
  }
  pthread_cond_wait(&carFull, &rollerCoasterLock);
  pthread_cond_wait(&carUnload, &rollerCoasterLock);
  printf("Passenger %d left car.\n", passenger_id);
  pthread_mutex_unlock(&rollerCoasterLock);
  pthread_exit(0);
}

void load(){
  pthread_mutex_lock(&rollerCoasterLock);
  // if(numPass==0)
  //   pthread_exit(NULL);
  while(passengersInCar>0){
    pthread_cond_wait(&carUnload, &rollerCoasterLock);
  }
  carIsWaiting = true;
  pthread_cond_broadcast(&carLoad);
  printf("Car is waiting for passengers.\n");

  pthread_cond_wait(&carFull, &rollerCoasterLock);
  carIsWaiting = false;
  pthread_cond_broadcast(&carFull);
  printf("Car is full. Going around...\n" );
  pthread_mutex_unlock(&rollerCoasterLock);
}

void unload(){
  pthread_mutex_lock(&rollerCoasterLock);

  pthread_cond_broadcast(&carUnload);
  puts("unloading...");
  passengersInCar=0;
  pthread_mutex_unlock(&rollerCoasterLock);
  // pthread_exit(0);
}

主要

#include <pthread.h>
#include <unistd.h>
#include "rollerCoaster.h"

void* carThreadFunction();
void* passengerThreadFunction(int passenger_id);
void testRollerCoasterOneCar(int carCapacity, int numPassengers);
int cap, numPass;
pthread_attr_t threadAttributes;

int main(int argc, char *argv[]) {

  passengersInCar = 0;
  carIsWaiting = false;
  pthread_mutex_init(&rollerCoasterLock, NULL);
  pthread_cond_init(&carLoad, NULL);
  pthread_cond_init(&carUnload, NULL);
  pthread_cond_init(&carFull, NULL);
  //check command line args
  if (argc != 3){
      puts("Please enter (car-capacity-num) and (num-of-passengers).\n");
      exit(0);
  } else {
    cap = atoi(argv[1]);
    numPass = atoi(argv[2]);
  }
  pthread_attr_init(&threadAttributes);
    pthread_attr_setscope(&threadAttributes, PTHREAD_SCOPE_SYSTEM);

  testRollerCoasterOneCar(cap, numPass);

  pthread_join(carThread, NULL);
  puts("done");
  return 0;
}

void testRollerCoasterOneCar(int carCapacity, int numPassengers) {
    // rollerCoasterOneCar = new RollerCoasterOneCar(carCapacity);

    pthread_t carThread;
    pthread_create(&carThread, &threadAttributes, (void*) carThreadFunction, (void*) NULL);

    pthread_t passengersThreads[numPassengers];
    for (int i = 0; i < numPassengers; i++) {
        pthread_create(&passengersThreads[i], &threadAttributes, (void*) passengerThreadFunction, (void*)i);
    }
}

void* carThreadFunction(){
  while(true){
    load();
    usleep(100000);
    unload();
  }
  return NULL;
}

void* passengerThreadFunction(int passenger_id){
  while(true){
    takeRide(passenger_id);
  }
  return NULL;
}

0 个答案:

没有答案