课时68_循环创建多个子线程和注意事项
文章目录
1、打印多个线程序号和线程ID
1.1、代码实现
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <pthread.h> //线程对应的头文件
//回调函数,子线程要做的任务
void* myfun(void* arg)
{
//取出传递来的参数(子线程序号)
int index = *(int*)(arg);
//打印子线程的序号和线程ID
printf("%d th child thread id:%ld\n",index,pthread_self());
return NULL;
}
#define PTHTEAD_CREAT_NUM (5)
//主函数
int main()
{
//循环创建5个子线程
pthread_t pthid[PTHTEAD_CREAT_NUM];
for(int i=0;i<PTHTEAD_CREAT_NUM;i++)
{
//将子线程序号通过传参,传递给子线程的函数
//第4个参数传递的是地址
pthread_create(&pthid[i],NULL,myfun,(void*)&i);
}
//打印父线程ID
printf("parent thread id:%ld\n",pthread_self());
//让父线程sleep两秒,保证子线程先结束,父线程后结束
sleep(2);
return 0;
}
1.2、执行结果:
root@Ubuntu18:/home/remotefs/001.Linux_sys# gcc pthread_creat_5.cpp -lpthread
root@Ubuntu18:/home/remotefs/001.Linux_sys# ./a.out
4 th child thread id:140575567603456
parent thread id:140575576119104
5 th child thread id:140575550818048
5 th child thread id:140575559210752
5 th child thread id:140575542425344
5 th child thread id:140575534032640
1.3、分析结果:
子线程序号并没有按照预期的结果(0~4)打印,但每个子线程ID的打印结果是不同的。
1.4、根源分析:
子线程1在抢cpu后,输出子线程1信息打印结果前失去cpu,cpu被子线程2抢占,子线程2会将main()函数中的i
值改变。由于回调函数传递的参数是主线程的栈区中i
的地址,所以等子线程1再次抢到cpu输出打印结果时,i
的值已经改变,打印结果中线程序号也就比原来要大。
2、打印多个线程序号和线程ID优化
2.1、代码优化
增加一个子线程ID的数组int g_pthreadid[PTHTEAD_CREAT_NUM]={0,1,2,3,4};
传递序号时传递数组中已经确定的序号pthread_create(&pthid[i],NULL,myfun,(void*)&g_pthreadid[i]);
,保证子线程序号不被其他线程修改。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <pthread.h> //线程对应的头文件
//回调函数,子线程要做的任务
void* myfun(void* arg)
{
//取出传递来的参数(子线程序号)
int index = *(int*)(arg);
//打印子线程的序号和线程ID
printf("%d th child thread id:%ld\n",index,pthread_self());
return NULL;
}
//创建子线程个数
#define PTHTEAD_CREAT_NUM (5)
//子线程序号数组
int g_pthreadid[PTHTEAD_CREAT_NUM]={0,1,2,3,4};
//主函数
int main()
{
//循环创建5个子线程
pthread_t pthid[PTHTEAD_CREAT_NUM];
for(int i=0;i<PTHTEAD_CREAT_NUM;i++)
{
//将子线程序号通过传参,传递给子线程的函数
//第4个参数传递的是地址,但地址不被其他线程修改
pthread_create(&pthid[i],NULL,myfun,(void*)&g_pthreadid[i]);
}
//打印父线程ID
printf("parent thread id:%ld\n",pthread_self());
//让父线程sleep两秒,保证子线程先结束,父线程后结束
sleep(2);
return 0;
}
2.2、执行结果:
root@Ubuntu18:/home/remotefs/001.Linux_sys# gcc pthread_creat_5.cpp -lpthread
root@Ubuntu18:/home/remotefs/001.Linux_sys# ./a.out
0 th child thread id:140512445683456
parent thread id:140512454199104
2 th child thread id:140512428898048
1 th child thread id:140512437290752
3 th child thread id:140512420505344
4 th child thread id:140512412112640
3、两种代码对比分析
在创建子线程,向子线程传递参数的时候,在传地址时需要注意是否会被其他线程修改。