Linux系统编程_课时68_循环创建多个子线程和注意事项

课时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、两种代码对比分析

在创建子线程,向子线程传递参数的时候,在传地址时需要注意是否会被其他线程修改。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值