gpt4 book ai didi

c++ - POSIX 线程同步和/或 pthread_create() 参数传递问题

转载 作者:太空宇宙 更新时间:2023-11-04 16:12:47 25 4
gpt4 key购买 nike

我正在尝试创建许多不同的线程,这些线程需要等待所有线程创建完毕才能执行任何操作。这是一个大程序的一小部分,我只是想逐步进行。当创建每个线程时,它会立即被信号量阻塞。创建所有线程后,我遍历并释放所有线程。然后我希望每个线程都打印出它的线程号以验证它们是否都在等待。我只允许一个线程使用另一个信号量一次打印。

我遇到的问题是,虽然我创建了线程 #1-10,但线程打印出它是 #11。此外,一些线程说它们与另一个线程具有相同的编号。是我传递 threadID 时出错还是同步时出错?

相关代码如下:

//Initialize semaphore to 0. Then each time a thread is spawned it will call
//semWait() making the value negative and blocking that thread. Once all of the
//threads are created, semSignal() will be called to release each of the threads
sem_init(&threadCreation,0,0);


sem_init(&tester,0,1);


//Spawn all of the opener threads, 1 for each valve
pthread_t threads[T_Valve_Numbers];
int check;

//Loop starts at 1 instead of the standard 0 so that numbering of valves
//is somewhat more logical.
for(int i =1; i <= T_Valve_Numbers;i++)
{
cout<<"Creating thread: "<<i<<endl;
check=pthread_create(&threads[i], NULL, Valve_Handler,(void*)&i);
if(check)
{
cout <<"Couldn't create thread "<<i<<" Error: "<<check<<endl;
exit(-1);
}
}

//Release all of the blocked threads now that they have all been created
for(int i =1; i<=T_Valve_Numbers;i++)
{
sem_post(&threadCreation);
}

//Make the main process wait for all the threads before terminating
for(int i =1; i<=T_Valve_Numbers;i++)
{
pthread_join(threads[i],NULL);
}
return 0;



}
void* Valve_Handler(void* threadNumArg)
{
int threadNum = *((int *)threadNumArg);
sem_wait(&threadCreation);//Blocks the thread until all are spawned

sem_wait(&tester);
cout<<"I'm thread "<<threadNum<<endl;
sem_post(&tester);
}

当 T_Valve_Numbers = 10 时,一些示例输出为:

Creating thread: 1
Creating thread: 2
Creating thread: 3
Creating thread: 4
Creating thread: 5
Creating thread: 6
Creating thread: 7
Creating thread: 8
Creating thread: 9
Creating thread: 10
I'm thread 11 //Where is 11 coming from?
I'm thread 8
I'm thread 3
I'm thread 4
I'm thread 10
I'm thread 9
I'm thread 7
I'm thread 3
I'm thread 6
I'm thread 6 //How do I have 2 6's?

Creating thread: 1
Creating thread: 2
Creating thread: 3
Creating thread: 4
Creating thread: 5
Creating thread: 6
Creating thread: 7
Creating thread: 8
Creating thread: 9
Creating thread: 10
I'm thread 11
I'm thread 8
I'm thread 8
I'm thread 4
I'm thread 4
I'm thread 8
I'm thread 10
I'm thread 3
I'm thread 9
I'm thread 8 //Now '8' showed up 3 times

“我是线程...”打印了 10 次,所以看起来我的信号量正在让所有线程通过。我只是不确定为什么他们的线程号搞砸了。

最佳答案

check=pthread_create(&threads[i], NULL, Valve_Handler,(void*)&i);
^^

您将 i 的地址传递给线程启动函数。 i 在主循环中一直在变化,与线程函数不同步。一旦线程函数开始实际取消引用该指针,您就不知道 i 的值是多少。

如果这是您唯一需要传递的东西,则传递一个实际的整数而不是指向局部变量的指针。否则,创建一个包含所有参数的简单 struct,构建这些参数的数组(每个线程一个)并向每个线程传递一个指向其自身元素的指针。

示例:(假设您的线程索引永远不会溢出 int)

#include <stdint.h> // for intptr_t

...
check = pthread_create(..., (void*)(intptr_t)i);
...

int threadNum = (intptr_t)threadNumArg;

更好/更灵活/不需要可能不存在的 intprt_t 示例:

struct thread_args {
int thread_index;
int thread_color;
// ...
}

// ...

struct thread_args args[T_Valve_Numbers];
for (int i=0; i<T_Valve_Numbers; i++) {
args[i].thread_index = i;
args[i].thread_color = ...;
}

// ...

check = pthread_create(..., &(args[i-1])); // or loop from 0, less surprising

尽管如此,请注意:线程参数数组需要至少在线程使用它时保持事件状态。在某些情况下,您最好为每个结构进行动态分配,将该指针(及其所有权)传递给线程函数(尤其是如果您要分离线程而不是加入它们)。

如果您打算在某个时候加入线程,请像保留 pthread_t 结构一样保留这些参数。 (如果您在同一个函数中创建和加入,堆栈通常就可以了。)

关于c++ - POSIX 线程同步和/或 pthread_create() 参数传递问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26452299/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com