POSIX线程同步和/或pthread_create()参数传递问题
Issue with POSIX thread synchronization and/or pthread_create() argument passing
我正在尝试创建许多不同的线程,这些线程需要等待所有线程创建完成才能执行任何操作。这是一个大型项目的一个小部分,我只是想循序渐进。当创建每个线程时,它会立即被信号量阻塞。创建完所有线程后,我循环遍历并释放所有线程。然后我希望每个线程打印出它的线程号,以验证它们是否都在等待。我一次只允许使用另一个信号量打印一个线程。
我遇到的问题是,尽管我创建了#1-10线程,但一个线程打印出它是#11。此外,一些线程表示它们与另一个线程具有相同的编号。是我传递线程ID时出错,还是我的同步中出错?
以下是相关代码:
//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++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 修改函数中的指针(将另一个指针作为参数传递)
- 如何将部分流作为参数传递
- 我正在开发服务器,ip作为参数传递不起作用
- 将成员函数指针作为参数传递给模板方法
- 如何在C++中将迭代器作为函数参数传递
- 将附加参数传递给使用 beast::bind_front_handler 调用的函数
- 如何将一个类的函数作为另一个类的另一个函数的参数传递
- 将参数传递为"const"的奇怪效果
- 如何在 c++ 中将函数作为参数传递?
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- 使用引用与指针将数组作为参数传递
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 将参数打包的参数传递到 std::queue 中,以便稍后使用不同的函数调用
- 为什么我不能将引用作为 std::async 的函数参数传递
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- QThread::create 似乎没有将参数传递给函数