当我尝试使用虚拟方法创建类实例并将其传递给pthread_create时,出现竞争情况,导致调用方有时调用基本方法,而不是像应有的那样调用派生方法。在搜索pthread vtable race
之后,我发现这是相当知名的行为。我的问题是,如何解决这个问题?
下面的代码在任何优化设置下都表现出此行为。请注意,在将MyThread对象传递给pthread_create之前,已对其进行了完全构造。
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Thread {
pthread_t thread;
void start() {
int s = pthread_create(&thread, NULL, callback, this);
if (s) {
fprintf(stderr, "pthread_create: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
}
static void *callback(void *ctx) {
Thread *thread = static_cast<Thread*> (ctx);
thread->routine();
return NULL;
}
~Thread() {
pthread_join(thread, NULL);
}
virtual void routine() {
puts("Base");
}
};
struct MyThread : public Thread {
virtual void routine() {
}
};
int main() {
const int count = 20;
int loop = 1000;
while (loop--) {
MyThread *thread[count];
int i;
for (i=0; i<count; i++) {
thread[i] = new MyThread;
thread[i]->start();
}
for (i=0; i<count; i++)
delete thread[i];
}
return 0;
}
最佳答案
唯一的问题是,您是在生成的线程执行该方法之前删除对象的,所以到那时子析构函数已经被触发,对象不再存在。
因此,它与pthread_create无关,无论您的时间安排如何,您都无法生成线程,为其提供一些资源并删除它们,然后他才有机会使用它们。
尝试一下,它将显示在生成的线程使用它们之前,主线程如何破坏obj:
struct Thread {
pthread_t thread;
bool deleted;
void start() {
deleted=false;
int s = pthread_create(&thread, NULL, callback, this);
if (s) {
fprintf(stderr, "pthread_create: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
}
static void *callback(void *ctx) {
Thread *thread = static_cast<Thread*> (ctx);
thread->routine();
return NULL;
}
~Thread() {
pthread_join(thread, NULL);
}
virtual void routine() {
if(deleted){
puts("My child deleted me");
}
puts("Base");
}
};
struct MyThread : public Thread {
virtual void routine() {
}
~MyThread(){
deleted=true;
}
};
另一方面,如果您只是在删除它们之前在main中进行了睡眠,则永远不会出现该问题,因为生成的线程正在使用有效资源。
int main() {
const int count = 20;
int loop = 1000;
while (loop--) {
MyThread *thread[count];
int i;
for (i=0; i<count; i++) {
thread[i] = new MyThread;
thread[i]->start();
}
sleep(1);
for (i=0; i<count; i++)
delete thread[i];
}
return 0;
}
关于c++ - 在虚拟函数和pthread_create之间进行竞争,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1802418/