pthread_create传入参数的一个问题

本文探讨了在使用多线程时遇到的一个常见问题:如何正确地将参数传递给线程函数。通过三个不同的解决方案,包括使用数组、动态内存分配以及类型转换,展示了如何避免因共享变量导致的打印错误。每个方法都有其优缺点,例如数组占用额外空间,动态内存需要手动管理,而类型转换则可能存在潜在风险。

背景题目

有一个线程函数thread_func,它的入参是一个整数,它的功能是打印出这个整数。要求循环启动10个线程,打印出1~10

错误写法

#include <pthread.h>

#define MAXN 10

void* thread_func(void* arg)
{
	printf("arg = %d\n", *(int*)arg);
}

int main()
{
	pthread_t tid[MAXN];
	for (int i = 0; i < MAXN; i++) {
		pthread_create(&tid[i], NULL, thread_func, &i);
	}

	for (int i = 0; i < MAXN; i++) {
		pthread_join(tid[i], NULL);
	}
	return 0;
}

执行结果
在这里插入图片描述
可以看到,打印出来的全都是10,而不是每轮循环传入的i

原因分析:我们传入的,不是变量i的值,而是i的地址,相当于一个指向i的指针。

因此在打印出该地址的i的值时,i的值已经被循环所改变了。

那么该怎么写呢?

解决方法1-数组

通过数组存储传入的变量值,可以保证参数不发生变化

#include <pthread.h>

#define MAXN 10

void* thread_func(void* arg)
{
	printf("arg = %d\n", *(int*)arg);
}

int main()
{
	int a[MAXN]; // 解决方法增加的数组
	pthread_t tid[MAXN];
	for (int i = 0; i < MAXN; i++) {
		a[i] = i;
		pthread_create(&tid[i], NULL, thread_func, &a[i]);
	}

	for (int i = 0; i < MAXN; i++) {
		pthread_join(tid[i], NULL);
	}
	return 0;
}

执行结果
在这里插入图片描述
但该方法的缺点是显而易见的:数组a占用了额外的空间。

方法2-malloc

将每次要传入的参数,通过malloc分配出一块专门的内存存放,用完释放。

#include <pthread.h>

#define MAXN 10

void* thread_func(void* arg)
{
	printf("arg = %d\n", *(int*)arg);
	free(arg); // 用完释放
}

int main()
{
	pthread_t tid[MAXN];
	for (int i = 0; i < MAXN; i++) {
		int *cnt = malloc(sizeof(int)); // 分配内存
		*cnt = i; // 赋值
		pthread_create(&tid[i], NULL, thread_func, cnt);
	}

	for (int i = 0; i < MAXN; i++) {
		pthread_join(tid[i], NULL);
	}
	return 0;
}

这样,每次传入的都是一个全新的地址来存储i的值。该方法需要注意的是要及时释放arg指向的内存,避免内存泄漏。

方法3-xjb转换指针

#include <pthread.h>

#define MAXN 10

void* thread_func(void* arg)
{
	printf("arg = %d\n", arg); // 注意这里不一样了
}

int main()
{
	pthread_t tid[MAXN];
	for (int i = 0; i < MAXN; i++) {
		pthread_create(&tid[i], NULL, thread_func, (void*)i); // 把i解释为(void*)
	}

	for (int i = 0; i < MAXN; i++) {
		pthread_join(tid[i], NULL);
	}
	return 0;
}

这里把i强制当作一个void*类型指针指向的地址传入,这样拿到的是一份拷贝,当然,输出时,不需要解引用。

这方法真的是emmm…

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值