2013-07-19 49 views
0

我写带班,并行线程,互斥体,和conds一个简单的理发店C/C++项目,但我遇到了一个问题,当我在一个循环中创建一个新的客户对象:并行线程循环覆盖指针

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:随着并行线程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] 
+0

你没有在你的类中存储客户ID作为一个静态成员变量是你吗?你能显示你的构造函数的代码吗? – Jimbo

+0

@Jimbo已更新。 – user622469

+1

在同一个堆栈上,它始终是同一个客户。 –

回答

1

在下面的部分

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

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

所以,当你做customers.push_back(c) a 副本的类是采取(见(default) copy constructor)并添加到客户名单。这意味着当你做c.start()时,你压入你的矢量的副本有而不是已经启动,只有环路本地的实例。在循环结束时,循环c的迭代被破坏。该循环再次开始并创建一个新的c

编辑: 见马丁詹姆斯和凯西的言论,为什么你看到的行为是发生

+0

其实......我错了......这正是问题所在。而不是c.start()我需要:customers [customers.size() - 1] .start();谢谢! – user622469

+1

我想你错过了凯西和马丁詹姆斯的几个要点。 – Jimbo

1

基于堆栈的汽车对象和多线程是犯错..‘在任何情况下不融洽’ :)

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

或者,vector :: emplace Customer对象到vector中,以使auto/stack Customer消失。