公司某个程序需要在启动时创建多个线程,我们使用for循环来一起创建,结果某些期望的线程一直创建不成功!
关键代码如下:
enum en_TaskId
{
TaskId_0 = 0,
TaskId_1,
TaskId_2,
TaskId_3,
TaskId_4,
TaskNum = 5
};
// 创建 5 个线程
void create_thread()
{
pthread_t thread;
for(u32 dwIndex = 0; dwIndex < TaskNum; dwIndex++)
{
TThreadInfo tThreadInfo = { 0 };
tThreadInfo.pcTask = this;
tThreadInfo.dwIndex = dwIndex;
Print("[start] pthread_create() dwIndex: %d\r\n", tThreadInfo.dwIndex);
pthread_create(&thread, NULL, thread_func,(void*)&tThreadInfo);
Print("[end] pthread_create() dwIndex: %d\r\n", tThreadInfo.dwIndex);
usleep(10000);
}
Print("create end\r\n");
}
// 线程函数
static void* thread_func(void* arg0)
{
TThreadInfo* pThis = (TThreadInfo*)arg0;
u32 nIndex = pThis->dwIndex;
Print("task create callback: 0x%x, idx: %d\n", pThis, nIndex);
pThis->pcTask->RealTaskProcess(nIndex);
}
结果打印如下:
[start] pthread_create() dwIndex: 0
[end] pthread_create() dwIndex: 0
task create callback: 0xb0edd8d0, idx: 1
[start] pthread_create() dwIndex: 1
task create callback: 0xb0edd8d0, idx: 1
[end] pthread_create() dwIndex: 1
[start] pthread_create() dwIndex: 2
[end] pthread_create() dwIndex: 2
task create callback: 0xb0edd8d0, idx: 3
[start] pthread_create() dwIndex: 3
[end] pthread_create() dwIndex: 3
task create callback: 0xb0edd8d0, idx: 4
[start] pthread_create() dwIndex: 4
[end] pthread_create() dwIndex: 4
task create callback: 0xb0edd8d0, idx: 4
create end
由上述打印可知:期待的 线程0 和 线程2 根本没有创建出来,
// 创建 5 个线程
void create_thread()
{
pthread_t thread;
for(u32 dwIndex = 0; dwIndex < TaskNum; dwIndex++)
{
TThreadInfo tThreadInfo = { 0 };
tThreadInfo.pcTask = this;
tThreadInfo.dwIndex = dwIndex;
Print("[start] pthread_create() dwIndex: %d\r\n", tThreadInfo.dwIndex);
pthread_create(&thread, NULL, thread_func,(void*)&tThreadInfo);
Print("[end] pthread_create() dwIndex: %d\r\n", tThreadInfo.dwIndex);
usleep(10000);
}
Print("create end\r\n");
}
原因是 create_thread() 中,线程函数参数是定义在for循环体中的临时变量。
这会导致一些负面影响:
首先,在 pthread_create 中,最好不要将 线程句柄 和 线程函数参数 定义成临时变量,
因为可能临时变量都销毁了,线程函数才姗姗来迟的被调用起来,此时的参数指针已经成了野指针了!!!
其次,在 for 循环体内定义临时变量,那么此变量可以认为在每次循环中都是一个独立的临时变量,但可能每次循环中的临时变量进栈出栈的变量地址都是一样的!这会导致 这次循环中的临时变量会被下次循环破坏,每次循环中的临时变量不再是独立的啦。还有可能C编译器对for循环中定义的临时变量有优化,优化成只用一个临时变量负责所有循环,这也会导致各次循环不在是独立的啦。
基于上面的分析,下面我们对 create_thread() 进行修改优化:
// 此次测试使用全局变量
pthread_t thread;
TThreadInfo tThreadInfo[TaskNum] = { 0 }; //定义大小为 5 的结构体数组
// 创建 5 个线程
void create_threadEx()
{
for(u32 dwIndex = 0; dwIndex < TaskNum; dwIndex++)
{
tThreadInfo[dwIndex].pcTask = this;
tThreadInfo[dwIndex].dwIndex = dwIndex;
Print("[start] pthread_create() dwIndex: %d\r\n", tThreadInfo[dwIndex].dwIndex);
pthread_create(&thread, NULL, thread_func, (void*)&tThreadInfo[dwIndex]);
Print("[end] pthread_create() dwIndex: %d\r\n", tThreadInfo[dwIndex].dwIndex);
usleep(10000);
}
Print("create end\r\n");
}
版权声明:本文为lijian2017原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。