C 对PTHREADS过于偏执?
在我查找的所有地方,我都找到了使用pthreads的教程和示例,该pthreads的指针指向函数调用的参数,该函数调用引用了主函数中的全局变量或局部变量。 另一方面,由于我不能使用全局变量,我有以下代码:C 对PTHREADS过于偏执?,c,variables,pthreads,local,C,Variables,Pthreads,Local,在我查找的所有地方,我都找到了使用pthreads的教程和示例,该pthreads的指针指向函数调用的参数,该函数调用引用了主函数中的全局变量或局部变量。 另一方面,由于我不能使用全局变量,我有以下代码: pthread_t thread; void *thread_created(void *np); void function2(int numParam); void function1(int numParam) { int cond=0; ... if (co
pthread_t thread;
void *thread_created(void *np);
void function2(int numParam);
void function1(int numParam)
{
int cond=0;
...
if (cond)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread,&attr,thread_created,&numParam);
}
}
void *thread_created(void *np)
{
int numParam;
numParam=*((int *)np);
function2(numParam);
return NULL;
}
void function2(int numParam)
{
}
然而,在我看来,在某些情况下,function1中的局部变量numParam可能在线程有机会获得其值之前超出范围。比赛条件。
因此,我修改了代码,使用全局互斥体和条件变量添加标有//的行是一种非常糟糕的方法。它基本上序列化了所有线程创建操作。有几种更好的方法可以将参数传递给新线程:
void*
并返回来忠实地表示,那么就这样做。这不需要任何同步,也不会分割内存。或者,如果您不想假设您可以像这样强制转换void*
,您可以通过const char dummy[N]支持较小范围的整数值0
到N
并将dummy+i
传递给pthread\u create
然后从thread start函数中接收的指针参数中减去dummy
。此变体是100%便携式的,即C标准要求其工作sem\t
成员。将结构放在父线程的堆栈上(自动存储在调用pthread\u create
的函数中)。在创建线程之前让父线程调用sem\u init
,在pthread\u create
之后返回sem\u wait
。一旦访问完参数(例如,将参数复制到自己的本地存储),新线程将调用sem\u post
,父线程将调用sem\u destroy
一次sem\u wait
返回。此时,新线程不再使用参数结构,因此父线程可以删除它,让它超出范围,等等malloc
。父线程通过malloc
为参数分配存储,新线程负责调用free
。我认为这种适度的重同步是因为,即使使用R.response,这是最终代码,以防有人需要它:
pthread_t thread;
sem_t semaphore;
void initialize_semaphore()
{
sem_init(&semaphore,0,1);
}
void destroy_semaphore()
{
sem_destroy(&semaphore);
}
void *thread_created(void *np);
void function2(int numParam);
void function1(int numParam)
{
int cond=0;
...
if (cond)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread,&attr,thread_created,&numParam);
sem_wait(&semaphore);
}
}
void *thread_created(void *np)
{
int numParam;
numParam=*((int *)np);
sem_post(&semaphore);
function2(numParam);
return NULL;
}
void function2(int numParam)
{
}
谢谢大家的回答
问候
alfredomeraz.为什么不在堆上为int添加malloc空间呢?那么,当线程完成时,它会被释放吗?这样,您就不会有在函数返回后访问变量的未定义行为。我考虑过,甚至创建一个结构,添加一个将在线程内更改的标志,向主线程发出值已更改的信号。我想我并没有真正理解您要做的事情。您想修改一个变量,但担心main()会践踏它?如果是这样,你需要一把锁。只要在结构中传递一个锁和一个指向变量的指针,然后每次读或写变量锁的时候都会这样做?@ScottyBauer说什么-不要再乱搞标志和互斥体了,只需要malloc这个该死的参数:)至于malloc的使用,它被丢弃是因为它会造成一种更难调试和克服的情况:在低资源环境中由于大量使用内存分配而导致堆碎片,这是因为低资源本身造成的。至于我提到的flag解决方案:这意味着,将它放入一个空循环,这会在资源不足的环境中占用资源。谢谢你的回答。我有些怀疑,你。如果您的第一个选项在没有竞争条件的意义上是正确的,那么我的第一段代码也是正确的(我仍然怀疑竞争条件的存在)。对于我在其他消息中所写的内容,我放弃您的第三个选项。你的第二个选择是我认为我真正缺少的答案。也许条件变量解决方案是可行的,但这种情况确实需要一个信号量。所以我接受你的回答。非常感谢:-)不。我的第一个选择是按值传递参数。不存在竞争条件,因为不存在任何共享对象。代码正在父线程中传递正在修改(或其生存期即将结束)的对象的地址。那完全不同。哇。。。我明白你的意思。。。“注入”参数的聪明方法。。。从没想过那样做。。。但是你的权利:-)。。。我采取这种方法。。。至少,在可行的地方,比如我现在面对的那个。。。在我的系统中的下一个ocurrances,如果它们不适合这种方法,我仍然有可用的信号量。。。再次非常感谢:-)
pthread_t thread;
sem_t semaphore;
void initialize_semaphore()
{
sem_init(&semaphore,0,1);
}
void destroy_semaphore()
{
sem_destroy(&semaphore);
}
void *thread_created(void *np);
void function2(int numParam);
void function1(int numParam)
{
int cond=0;
...
if (cond)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread,&attr,thread_created,&numParam);
sem_wait(&semaphore);
}
}
void *thread_created(void *np)
{
int numParam;
numParam=*((int *)np);
sem_post(&semaphore);
function2(numParam);
return NULL;
}
void function2(int numParam)
{
}