C ++ pthreads / semaphores表现不佳

时间:2013-12-09 08:27:16

标签: c++ multithreading pthreads semaphore

我是C ++新线程的新手,我确信它会在我的问题中显示出来。

我正在为一所学校的项目工作,我需要建立一个4路交通路口的模型,其中汽车是线程。我有一个时钟计数器,每个时钟滴答我生成一个随机数量的汽车,为每一个创建一个简单的汽车对象,将新车放入4个队列(街道)中的一个,然后做一个pthread来处理汽车。每辆车必须等到它到达街道的前面,然后等待一个信号,表明一辆车可以去。因此,如果有多辆汽车在十字路口等候,那么首先没有任何订单。

但是,我遇到了问题。根据我的打印输出,一个线程将运行,退出,但然后它将再次返回等待信号量。当它获得信号量并尝试用汽车做事时,这会发生段错误。任何正确方向的指针都会很棒!

示例输出为:

Running with 10 cars
  |    |    |  
2: Generating 3 cars. Already scheduled: 0, finished: 0
2:  Generating car 2-0 at street 3
2:  Generating car 2-1 at street 3
2:  Generating car 2-2 at street 0
waiting for clk in main
2-2 waiting for turn
2: Car 2-2 driving from street 0
waiting for streets in departure
2-2  |    |    |  2-0, 2-1
  |    |    |  2-0, 2-1
releasing streets in departure
2-2 releasing clock
2-2 exiting
got clk in main
  |    |    |  2-0, 2-1
4: Generating 3 cars. Already scheduled: 3, finished: 1
2-22-2 waiting for turn
4:  Generating car 4-0 at street 1
 waiting for turn
4:  Generating car 4-1 at street 1
4:  Generating car 4-2 at street 2
4-2 waiting for turn
waiting for clk in main
4: Car 2-2 driving from street 0
waiting for streets in departure
  |  4-0, 4-1  |  4-2  |  2-0, 2-1
Segmentation fault (core dumped)

我的主要方法:

int numCars = 0;
deque<deque<Car> > streets; //each queue for each street
bool empty = true; // intersection is empty (Boolean)
int clk = 0; // clock counter
int carsFinished = 0;
int carsScheduled = 0;
sem_t turn;
sem_t streetSem;
sem_t sigSem;
sem_t clkSem;


int main () {
   deque<Car> street0, street1, street2, street3;
   streets.push_back(street0);
   streets.push_back(street1);
   streets.push_back(street2);
   streets.push_back(street3);

   printf("Please enter the number of cars to run:  ");
   cin >> numCars;
   cout << "\nRunning with " << numCars << " cars\n";

   sem_init(&turn, 0, 0);
   sem_init(&streetSem, 0, 1);
   sem_init(&sigSem, 0, 0);
   sem_init(&clkSem, 0, 0);

   while (carsFinished < numCars) {

      // Generate a random number of cars, from 0 to 5
      double r = rndom();
      int numCarsThisRound;
      if (r == 1.0) {
         numCarsThisRound = 5; // so it won't go to 6
      } else {
         numCarsThisRound = r * 6.0;
      }
      int i = 0;

      if ((carsScheduled < numCars) && ((carsScheduled - carsFinished) < 110) && (i < numCarsThisRound)) {
         sem_wait(&streetSem);
         print_streets();
         sem_post(&streetSem);
         cout << clk << ": Generating " << numCarsThisRound << " cars. Already scheduled: " << carsScheduled << ", finished: " << carsFinished << "\n";
      }

      //       there are still cars      there aren't more than 110 cars waiting    we don't go over the number of cars for this clock
      while ((carsScheduled < numCars) && ((carsScheduled - carsFinished) < 110) && (i < numCarsThisRound)) {

         // assign each car to a random street
         double r = rndom();
         int num;
         if (r == 1.0) {
            num = 3; // so it won't go to 4
         } else {
            num = r * 4.0;
         }

         // make new car
         Car car;
         car.setQueue(num);
         std::ostringstream s;
         s << clk << "-" << i;
         std::string id(s.str());
         car.setId(id);

         cout << clk << ":\tGenerating car " << car.id << " at street " << num << "\n";

         sem_wait(&streetSem);
            // if this is the first car in a street, let it know
            if (streets[num].empty())
               car.isFront = true;
            streets[num].push_back(car);
         sem_post(&streetSem);

         // make new thread for that car
         pthread_t pt;
         pthread_create(&pt, NULL, &arrival, (void *)&car);

         carsScheduled++;
         i++;
      }

      // if there's a car that should go this clk
      if (!streetsAreEmpty()) {
         // wait until that car runs before incrementing clk
         sem_post(&turn);
         cout << "waiting for clk in main\n";
         sem_wait(&clkSem);
         cout << "got clk in main\n";
      }
      clk++;

   }

   return (0);
}

线程使用的其他方法:

// car arrives at street
void* arrival(void *v) {
   Car car = *(Car*)v;

      // block until I'm at the front of the queue
      while (true) {
         if (car.isFront) {
            break;
         }
      }
      cout << car.id << " waiting for turn\n";
      sem_wait(&turn); // wait for it to be someone's turn
         cout << car.id << " waiting for signal\n";
            cout << clk << ": Car " << car.id << " driving from street " << car.queue << "\n";
            drive();
            departure(car.queue);
            cout << car.id << " releasing clock\n";
         sem_post(&clkSem); // let the main method know I'm done


   cout << car.id << " exiting\n";
   pthread_exit(NULL);
}


// departure of car from intersection
void departure(int i) {
   // one car departs
   cout << "waiting for streets in departure\n";
   sem_wait(&streetSem);
      print_streets();
      streets[i].pop_front();
      if (!streets[i].empty()) {
         streets[i].front().isFront = true;
      }
      print_streets();
   cout << "releasing streets in departure\n";
   sem_post(&streetSem);

   carsFinished++;
}

// take up a clock tick to simulate driving
void drive() {
   clk++;
}

Car类标题 - 非常简单:

#ifndef CAR_H
#define CAR_H

class Car {
    #include <string>

    public:
        Car();
        Car(int);
        void setQueue(int);
        void setId(std::string);
        std::string id;
        int queue;
        bool isFront;
};

#endif

谢谢!

1 个答案:

答案 0 :(得分:1)

这是未定义的行为。

Car car是一个局部变量,一旦超出范围就会被销毁。

您假设在此之前制作了副本(Car car = *(Car*)v;),但这不一定正确。

改变汽车的使用寿命,每个螺纹应该有(一个堆分配?)。