以下内容全部来自于b站码农论坛的个人空间_哔哩哔哩_bilibili
这位大哥是一位顶级大佬,有兴趣学c++的都可以去看一下他的视频。并且他还开源了他自己的框架,非常好用。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
// 与客户端通信的主函数
void *mainfunc1(void *arg);
void *mainfunc2(void *arg);
void *mainfunc3(void *arg);
void *mainfunc4(void *arg);
void *mainfunc5(void *arg);
int var = 1;
int main()
{
pthread_t pthid1, pthid2, pthid3, pthid4, pthid5;
// 创建一个线程
if (pthread_create(&pthid1, NULL, mainfunc1, NULL)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
var++;
if (pthread_create(&pthid2, NULL, mainfunc2, NULL)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
var++;
if (pthread_create(&pthid3, NULL, mainfunc3, NULL)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
var++;
if (pthread_create(&pthid4, NULL, mainfunc4, NULL)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
var++;
if (pthread_create(&pthid5, NULL, mainfunc5, NULL)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
printf("pthid1=%lu\n", pthid1);
printf("pthid2=%lu\n", pthid2);
printf("pthid3=%lu\n", pthid3);
printf("pthid4=%lu\n", pthid4);
printf("pthid5=%lu\n", pthid5);
printf("等待子线程退出。\n");
pthread_join(pthid1, NULL);
printf("子线程1已退出。\n");
pthread_join(pthid2, NULL);
printf("子线程2已退出。\n");
pthread_join(pthid3, NULL);
printf("子线程3已退出。\n");
pthread_join(pthid4, NULL);
printf("子线程4已退出。\n");
pthread_join(pthid5, NULL);
printf("子线程5已退出。\n");
return 0;
}
void *mainfunc1(void *arg)
{
printf("我是%d线程\n",var);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func1 sleep lsec ok.\n", a);
}
pthread_exit(0); // 子线程退出,不影响主线程
}
void *mainfunc2(void *arg)
{
printf("我是%d线程\n", var);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func2 sleep lsec ok.\n", a);
}
pthread_exit(0); // 子线程退出,不影响主线程
}
void *mainfunc3(void *arg)
{
printf("我是%d线程\n", var);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func3 sleep lsec ok.\n", a);
}
pthread_exit(0); // 子线程退出,不影响主线程
}
void *mainfunc4(void *arg)
{
printf("我是%d线程\n", var);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func4 sleep lsec ok.\n", a);
}
pthread_exit(0); // 子线程退出,不影响主线程
}
void *mainfunc5(void *arg)
{
printf("我是%d线程\n", var);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func5 sleep lsec ok.\n", a);
}
pthread_exit(0); // 子线程退出,不影响主线程
}
这个代码就是创建线程,然后在每个函数中输出自己是第几个线程,按照这个代码来说我们输出的结果应该是一 一对应的。我们来看一下结果。
结果都是5,这里出现这种结果的原因就是你创建线程是按照顺序创建的,但是你的mainfunc()函数不一定是创建一个就输出一个,所以都是等主线程都执行完毕了,var这个时候已经等于5了,所以你最后输出的结果那肯定都是5。那么现在就来解决这个问题。
我们通过man pthread_create 可以看到这个函数的第四个参数是一个void *类型,这里引入一个强制类型转换的概念。
通常指针都是存地址,但是我这里我想传值进去,因为如果传地址那不就是和前面的全局变量没有什么区别了,所以这里我们要传值进去,就得强制类型转化一下。下面的这种强制类型转化很明显不可以,我们来看下报了什么错误
我们先看第一个报错,告诉我们大小不同,我们知道不同操作系统下的指针大小是不一样的,64位下8字节。所以我们改一下。
损失精度好办。
ok,这样我们就解决了如何传值的问题了。那么回到一开始的传参,我们修改一下。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
// 与客户端通信的主函数
void *mainfunc1(void *arg);
void *mainfunc2(void *arg);
void *mainfunc3(void *arg);
void *mainfunc4(void *arg);
void *mainfunc5(void *arg);
int main()
{
/*
// 不一样的强制类型转换
int ii = 10;
void *ptr1 = (void *)(long)ii;
int jj = (int)(long)ptr1;
long aa = 10;
void *ptr2 = (void *)aa;
long bb = (long)ptr2;
*/
int var = 1;
pthread_t pthid1, pthid2, pthid3, pthid4, pthid5;
// 创建一个线程
// pthread_create()第四个参数是void *,所以需要强制转化
if (pthread_create(&pthid1, NULL, mainfunc1, (void *)(long)var)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
var++;
if (pthread_create(&pthid2, NULL, mainfunc2, (void *)(long)var)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
var++;
if (pthread_create(&pthid3, NULL, mainfunc3, (void *)(long)var)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
var++;
if (pthread_create(&pthid4, NULL, mainfunc4, (void *)(long)var)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
var++;
if (pthread_create(&pthid5, NULL, mainfunc5, (void *)(long)var)!= 0)
{
printf("线程创建失败,程序退出。\n");
return -1;
}
printf("pthid1=%lu\n", pthid1);
printf("pthid2=%lu\n", pthid2);
printf("pthid3=%lu\n", pthid3);
printf("pthid4=%lu\n", pthid4);
printf("pthid5=%lu\n", pthid5);
printf("等待子线程退出。\n");
pthread_join(pthid1, NULL);
printf("子线程1已退出。\n");
pthread_join(pthid2, NULL);
printf("子线程2已退出。\n");
pthread_join(pthid3, NULL);
printf("子线程3已退出。\n");
pthread_join(pthid4, NULL);
printf("子线程4已退出。\n");
pthread_join(pthid5, NULL);
printf("子线程5已退出。\n");
return 0;
}
void *mainfunc1(void *arg)
{
printf("我是%d线程\n", (int)(long)arg);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func1 sleep lsec ok.\n", a);
}
pthread_exit(0); // 子线程退出,不影响主线程
}
void *mainfunc2(void *arg)
{
printf("我是%d线程\n",(int)(long)arg);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func2 sleep lsec ok.\n", a);
}
}
void *mainfunc3(void *arg)
{
printf("我是%d线程\n", (int)(long)arg);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func3 sleep lsec ok.\n", a);
}
}
void *mainfunc4(void *arg)
{
printf("我是%d线程\n", (int)(long)arg);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func4 sleep lsec ok.\n", a);
}
}
void *mainfunc5(void *arg)
{
printf("我是%d线程\n", (int)(long)arg);
for (int ii = 0; ii < 10; ++ii)
{
// a++;
sleep(1);
// printf("a = %d func5 sleep lsec ok.\n", a);
}
}
再来看一下结果。
这样就都分开了,顺序不一样是正常的,因为编译器的优化问题,所以顺序不一样很正常,我们只需要知道结果是每一个线程都知道了自己准确的编号了。
还有一个解决方案那就是在每一个var++前面sleep(1);但是这样会耗时间。
总结,主要是说一下pthread_create()函数的参数传递。