pthread循环覆盖指针

时间:2013-07-19 16:22:42

标签: c++ multithreading pthreads

我正在编写一个简单的理发店C / C ++项目,包含类,pthread,互斥和conds,但是当我在循环中创建一个新的客户对象时,我遇到了一个问题:

void BarberShop::simulate() {
barber.start(); // start the barber
int custId = 1;
while(1) {
    Customer c(custId, *this);
    customers.push_back(c);
    c.start();
    sleep(3);
    custId++;
}

}

void Customer::start() {
    pthread_create(&thread, NULL, &Customer::run, this);
}

void* Customer::run(void *ptr) {
    Customer* data = reinterpret_cast<Customer*>(ptr);
    while(1) {
        printf("Customer %d running...\n", data->id);
        sleep(3);
    }
}

当我运行这个程序时,它会创建很好的线程,但每当我创建一个新线程时,它将覆盖其他线程中的id。输出:

Customer 1 running... 1 sec
Customer 1 running... 2 sec
Customer 1 running... 3 sec
Customer 2 running... 4 sec
Customer 2 running... 4 sec

在循环中我说:

Customer c(...);

这不是每次循环迭代都会创建一个新实例吗?为什么后续的线程会覆盖这个?

更新

class Customer
{
private:
    pthread_t thread;
    pthread_cond_t cond;
    pthread_mutex_t mutex;
    static void* run(void *args);
    int id;
    BarberShop *bs;
public:
    Customer(int _id, BarberShop &_bs);
    ~Customer();
    void start();
}; 

Customer::Customer(int _id, BarberShop &_bs) {
id = _id;
bs = &_bs;
}

更新2:使用pthread id

Customer 1 running...[3066383168]
Customer 2 running...[3057990464]
Customer 2 running...[3057990464]
Customer 3 running...[3049597760]
Customer 3 running...[3049597760]
Customer 3 running...[3049597760]
Customer 3 running...[3049597760]
Customer 4 running...[3049597760]
Customer 4 running...[3041205056]
Customer 4 running...[3041205056]
Customer 4 running...[3041205056]
Customer 5 running...[3041205056]
Customer 4 running...[3041205056]
Customer 5 running...[3032812352]
Customer 5 running...[3032812352]

2 个答案:

答案 0 :(得分:1)

在以下部分

while(1) {
    Customer c(custId, *this);
    customers.push_back(c);
    c.start();
    sleep(3);
    custId++;
}

类实例c是while循环范围的本地。在循环的每次迭代结束时,c被销毁。

因此,当您执行customers.push_back(c)时,会获取该课程的副本(请参阅(default) copy constructor)并添加到客户列表中。这意味着当您执行c.start()时,您推送到矢量上的副本已启动 ,只有循环本地的实例。在循环结束时,循环c的迭代被破坏。循环再次启动,并创建一个新的c

编辑: 请参阅Martin James和Casey的评论,了解为什么您所看到的行为正在发生

答案 1 :(得分:1)

基于堆栈的自动对象和多个线程错误..'在所有情况下都不协调':)

您可以使用Customer *的向量,如Casey所建议的那样。如果要通过引用将对象传递给线程,请使用new动态分配它们。这解决了同步对象等的不可复制性问题,并确保每个线程获得其自己的*对象。线程获得所有权,如果需要在进程终止之前终止,则需要删除传递的*对象。

或者,vector ::将Customer对象置于向量中,以便auto / stack Customer消失。