首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++ pthread/信号量不起作用

C++ pthread/信号量不起作用
EN

Stack Overflow用户
提问于 2013-12-09 16:27:16
回答 1查看 901关注 0票数 1

我是C++中的线程新手,我相信在我这里的问题中可以看到这一点。

我正在为学校的一个项目工作,我需要建立一个4向交通交叉路口的模型,其中汽车是线程。我有一个时钟计数器,每个时钟节拍我生成一个随机数量的汽车,为每个汽车创建一个简单的汽车对象,将新汽车放入4个队列(街道)中的一个队列中,然后创建一个pthread来处理汽车。每辆车必须等到它到达它的街道的前面,然后等待信号灯信号,指示汽车可以行驶。因此,如果有多辆车在十字路口等待,就没有任何顺序来决定哪辆车先走。

然而,我遇到了一些问题。根据我的打印输出,线程将运行、退出,但随后它将再次返回等待信号量。当它获得信号量并尝试对汽车做一些事情时,它就会分段。任何指向正确方向的指针都将是非常棒的!

示例输出为:

代码语言:javascript
运行
复制
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)

我的主要方法:

代码语言:javascript
运行
复制
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);
}

线程使用的其他方法:

代码语言:javascript
运行
复制
// 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类头-非常简单:

代码语言:javascript
运行
复制
#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

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2013-12-09 16:44:13

这是未定义的行为。

Car car是一个局部变量,一旦超出作用域,它就会被销毁。

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

改变汽车的寿命,应该有(堆分配了吗?)每个线程一个。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20466178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档