C++ pthreads/semaphores 不运行

标签 c++ multithreading pthreads semaphore

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

我正在为学校做一个项目,我需要为一个 4 向交通交叉路口建模,其中汽车是线程。我有一个时钟计数器,每个时钟滴答我都会生成随机数量的汽车,为每辆汽车创建一个简单的 Car 对象,将那辆新汽车放入 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 类 header - 非常简单:

#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

谢谢!

最佳答案

这是未定义的行为。

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

您假设在发生这种情况之前制作了一个拷贝 (Car car = *(Car*)v;),但这不一定正确。

改变汽车的生命周期,每个线程应该(分配一个堆?)一个。

关于C++ pthreads/semaphores 不运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20466178/

相关文章:

c++ - Python scons 构建

c++ - 在 C++ 中具有相同类的属性

c++ - 内存访问冲突错误c++

C# SpinWait 实现长时间等待

c - 如何同步线程?

c - 创建用户输入的多个线程时出现段错误

c++ - 在 Cygwin 上编译 MongoDB C++ 驱动程序

windows - 如果没有 "Cross Threading",我可以从 BackgroundWorker 访问什么?

java - android 中如何允许两个线程按预定义的顺序执行?

c - 将参数传递给 pthread 会导致重复 C