1、线程执行函数的参数:
pthread_create(线程地址,线程属性(NULL),线程执行哪个函数的名字,将主线程中的参数的地址给到线程执行函数作为参数。)
如:在主线程中,给出线程执行函数所需要的参数为int a,假设a的地址为0x12345;
创建线程,pthread_create(&th1, NULL, myfunc, &a)
线程执行函数:void* myfunc(void* agrs){ };&a = agrs,args的值就是0x12345,传入到线程执行函数的参数就是主线程中给出的参数的地址,是一个。因此,在线程执行函数如果要修改主线程中给出的参数,也可以通过不设置返回值,用指针来实现。比如:void* myfunc(void* agrs){ int* p = (int*)agrs, *p = 6 };那么主线程中的a变量的值已经变为6。
2、多个线程函数是否会对操作的变量有冲突,加锁等:
如果多个线程操作的变量是同一个全局变量,那么需要加锁。如果是对各自建立的局部变量进行操作,那么在多个线程执行函数内部是互不影响的。但是如果是malloc,注意对内存的释放。
3、假共享:如果多个线程函数所操作的对象在内存中距离特别近的时候,比如紧挨着,实际上会造成假共享,影响程序运行速度,这个具体去查阅一下吧。
4、pthread_create(&th1, NULL, myfunc, &a)
th1:线程名称 myfunc:这个线程要执行的线程执行函数 &a:将主线程中给出的参数地址给到myfunc去做处理。
5、pthread_join与pthread_exit
pthread_exit:用于线程执行函数中,用于返回线程执行函数的返回值。返回的是返回值的指针:
pthread_exit( (void*)myfunc_result );
pthread_join:用在主线程中,用于等待线程结束并接收线程执行函数返回的返回值的地址。
void* threcv_result: 在主线程中创建一个指针变量接收线程执行函数返回值的地址。
pthread_join(th[i],&threcv_result); 实际上: threcv_result = myfunc_result=线程执行函数中开辟的动态内存空间,虽然pthread_join的参数是threcv_result的地址,实际上执行的是根据threcv_result的地址将threcv_result的值设置为 pthread_exit中的存储线程执行函数返回值的地址。
pthread_join相当于将线程执行函数返回值的地址带回到主线程中。
下面这个代码有助于理解pthread_join是如何把线程执行函数的返回值带回到主调函数中的:
#include<stdlib.h>
#include<pthread.h>
#include<stdio.h>
void* func(void* agrs)
{
int* a = (int*)calloc(3,4);
printf("the value of a is %p\n\n",a);
pthread_exit((void*)a);
return;
}
int main(void)
{
pthread_t th;
pthread_create(&th, NULL, func, NULL);
void* b;
pthread_join(th, &b);
printf("the value of b is %p\n\n",b);
return 0;
}
打印结果为:a和b的值是一样的,都指向了在线程执行函数中动态分配的那块内存。pthread_join相当于带回了在线程执行函数中动态分配的内存。
6、pthread_exit:执行pthread_exit后,线程执行函数中定义的局部变量所在的栈区被释放。因此,不能把线程执行函数中局部变量的地址作为pthread_exit的参数,pthread_exit的参数应该是在静态区或者堆区等不会随线程执行函数销毁的区域。
参见:https://blog.csdn.net/modi000/article/details/104684582/
void* mufunc(void* p)
{
int a = 9;
int* q = &a;
// printf("q value is %p = \n",q);
pthread_exit((void*) q);
return NULL;
}
int main(void)
{
pthread_t th;
int a = 5;
printf("a address is %p\n", &a);
void* p;
pthread_create(&th, NULL, mufunc, &a);
pthread_join(th, &p);
printf("p = %p\n", p);
printf("%d\n", *(int*)p);//运行程序,这里无法输出,因为该地址已经被释放。
}
从下面这个程序中,也可以看到pthread_exit和pthread_exit的入参出参,其实都是同样的地址。
void* mufunc(void* p)
{
int* q = (int*)p;
*q = 8;
printf("q value is %p = \n",q);
pthread_exit((void*) q);
return NULL;
}
int main(void)
{
pthread_t th;
int a = 5;
printf("a address is %p\n", &a);
void* p;
pthread_create(&th, NULL, mufunc, &a);
pthread_join(th, &p);
printf("p = %p\n", p);
printf("%d\n", *(int*)p);//可以正常输出,因为变量a是定义在主线程中的,这个地址不会受mufunc中的pthread_exit的执行而被释放。
}
当不同的指针存储同样的地址时,这些指针都可以对那个地址上的变量进行操作。
7、多线程的malloc与free:在线程执行函数中malloc的指针,可以在主线程中free。在不同线程中,函数malloc的区域是独立的,不是共用的。而且每个线程的pthread_join返回的是自己线程的malloc指针,free即可。
8、可以多用printf打印看看实际情况。
9、多根据数据结构想一下,画一下图。