C语言-多线程-线程执行函数、互斥锁\线程函数malloc与free

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、多根据数据结构想一下,画一下图。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个利用多线程处理大文件的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define THREAD_COUNT 4 // 线程数量 struct ThreadParam { FILE *fp; // 文件指针 long long start; // 读写起始位置 long long end; // 读写结束位置 char *buffer; // 缓冲区 }; void *threadFunc(void *arg) { struct ThreadParam *param = (struct ThreadParam *) arg; FILE *fp = param->fp; fseek(fp, param->start, SEEK_SET); // 设置读写起始位置 fread(param->buffer, 1, param->end - param->start, fp); // 读取数据到缓冲区 // 对缓冲区中的数据进行处理 // ... pthread_exit(NULL); } int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: %s <filename>\n", argv[0]); exit(EXIT_FAILURE); } FILE *fp = fopen(argv[1], "rb"); if (!fp) { printf("Failed to open file %s\n", argv[1]); exit(EXIT_FAILURE); } fseek(fp, 0, SEEK_END); long long fileSize = ftell(fp); // 获取文件大小 long long chunkSize = fileSize / THREAD_COUNT; // 计算每个线程处理的块大小 char *buffer = (char *) malloc(chunkSize); // 创建缓冲区 pthread_t threads[THREAD_COUNT]; struct ThreadParam params[THREAD_COUNT]; for (int i = 0; i < THREAD_COUNT; i++) { params[i].fp = fp; params[i].buffer = buffer; params[i].start = i * chunkSize; params[i].end = (i == THREAD_COUNT - 1) ? fileSize : (i + 1) * chunkSize; pthread_create(&threads[i], NULL, threadFunc, &params[i]); // 创建线程 } for (int i = 0; i < THREAD_COUNT; i++) { pthread_join(threads[i], NULL); // 等待线程结束 } free(buffer); // 释放缓冲区 fclose(fp); // 关闭文件 return 0; } ``` 该示例代码中,首先通过 fseek 和 ftell 函数获取文件大小,然后计算出每个线程处理的块大小,创建缓冲区并分别创建多个线程进行读取和处理,最后等待线程结束并释放缓冲区和关闭文件。需要注意的是,对于多线程读写文件,需要考虑线程同步和互斥问题,可以使用互斥锁和条件变量来解决。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小哇123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值