Linux 多线程编程实例

本文详细介绍了Linux系统下多线程与多进程的区别,重点对比了它们的优势,并通过实例演示了如何使用pthread库创建、等待及终止线程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、多线程 VS 多进程

和进程相比,线程有很多优势。在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护代码段和数据。而运行于一个进程中的多个线程,他们之间使用相同的地址空间。正是这样,同一进程下的线程之间共享数据空间,数据可以相互使用,并且线程间切换也要更快些,可以更有效的利用CPU。

二、程序设计

[注] 头文件<pthread.h> 编译时要加载动态库 libpthread.a,使用 -lpthread
 
1、创建线程
2、等待线程
3、关闭线程
4、退出清除
 
1、创建线程


int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, void *(*start_rtn)(void), void *arg)

tidp为线程id,是函数分配的值,所以要传一个 pthread_t 的地址。
attr线程属性,通常为空。
start_rtn为线程要执行的函数,返回值为空指针,参数为后面的*arg
若成功则返回0,否则返回出错编号。
 
例:

 


#include<stdio.h>
#include<pthread.h></p> <p>void *func1(void *arg){ //原函数声明
int i;
for(i=0;i<5;i++){
printf("this is func1! The num is %d\n",*(int*)arg); //将空指针转换为int型指针
sleep(1);
}
}</p> <p>void *func2(int *m){ //自定义类型声明,也可以定义非指针类型,但是在create时会有警告,因为非地址并不能改变传入的值
int i;
for(i=0;i<5;i++){
printf("this is func2! The num is %d\n",*m);
(*m)++;
sleep(1);
}
}</p> <p>int main(){
pthread_t id1,id2;
int num = 5;
int *p = &num;
if(pthread_create(&id1,NULL,(void *)func1,(void *)p) != 0){
printf("thread1 create error!\n");
return -1;
}
if(pthread_create(&id2,NULL,(void *)func2,&num) != 0){
printf("thread2 create error!\n");
return -1;
}
pthread_join(id1,NULL); //等待线程结束  
pthread_join(id2,NULL);
printf("Running complete!\n");
return 0;</p> <p>
}

运行结果:

 


[fsy@localhost process]$ gcc thC.c -o thC -lpthread -g
[fsy@localhost process]$ ./thC
this is func2! The num is 5
this is func1! The num is 6
this is func2! The num is 6
this is func1! The num is 7
this is func2! The num is 7
this is func1! The num is 8
this is func2! The num is 8
this is func1! The num is 9
this is func2! The num is 9
this is func1! The num is 10
Running complete!
[fsy@localhost process]$


2、等待线程

[注]当调用pthread_create函数时,线程并没有开始执行,主进程应有等待,比如用sleep,或者用更专业的函数:pthread_join


int pthread_join(pthread_t tid, void **rval_ptr)

调用函数可以阻塞调用线程,直到指定的线程终止。
tid为等待退出线程的id,rval_ptr为函数的返回值。是指向指针的指针,可以置空。
 
例:


#include<stdio.h>
#include<pthread.h>
#include<stdlib.h></p> <p>void *func(int *p){
int *num=(int *)malloc(sizeof(int)); //必须动态创建,原因可以参考我动态分配内存的博客
printf("Please input the number: ");
scanf("%d",num);
return (void *)num; //类型是pthread_create的参数规定的
}</p> <p>int main(){
pthread_t pth;
void *a;
if(pthread_create(&pth,NULL,(void *)func,NULL) != 0){
printf("create thread error!\n");
return 1;
}
pthread_join(pth,&a); //指向空指针的指针
printf("get the num from the thread, it's %d\n",*(int *)a);
return 0;
}

3、终止线程

线程终止有以下三种方式:

1、线程从函数中返回
2、线程可以别其他函数终止
3、线程自己调用pthread_exit函数


void pthread_exit(void *rval_ptr)

rval_ptr为线程退出返回值的指针,即函数返回值。

4、退出清除


void pthread_cleanup_push(void (*rtn)(void*), void *arg)

rtn为清除函数,arg是清除函数的参数


void pthread_cleanup_pop(int execute)

当execute 非0时执行清除函数。为0时不执行。

从pthread_cleanup_push的调用点到pthread_cleanup_pop之间的程序段中,如果有终止进程的动作,如调用pthread_exit或异常终止(不包括return),就会执行pthread_cleanup_push()所指定的清理函数。多个嵌套匹配时,就近匹配。
 
例:


#include<stdio.h>
#include<pthread.h></p> <p>void *clean(char *argv){
printf("clean is called by %s\n",argv);
return NULL;
}
void *func1(void *argv){
printf("welcome enter the func1!\n");
pthread_cleanup_push((void*)clean,"the first time call!");
pthread_cleanup_push((void*)clean,"the second time call!");
if(argv){
return (void *)1; //第二次运行将此句注掉
}
pthread_cleanup_pop(0);
pthread_cleanup_pop(1);
return (void *)0;
}</p> <p>void *func2(void *argv){
sleep(1); //两个线程运行先后不确定
printf("welcome enter the func2!\n");
pthread_cleanup_push((void*)clean,"the first time call!");
pthread_cleanup_push((void*)clean,"the second time call!");
if(argv){
pthread_exit(NULL);
}
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
return (void *)0;
}</p> <p>
int main(){
pthread_t tid1,tid2;
if(pthread_create(&tid1,NULL,(void *)func1,(void *)1) != 0){
printf("thread1 create error!\n");
return 1;
}</p> <p> if(pthread_create(&tid2,NULL,(void *)func2,(void *)1) != 0){
printf("thread2 create error!\n");
return 1;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}

运行结果:


[fsy@localhost process]$ gcc thClean.c -o thclean -lpthread
[fsy@localhost process]$ ./thclean
welcome enter the func1!
welcome enter the func2!
clean is called by the second time call! //此处先2后1
clean is called by the first time call!
[fsy@localhost process]$ vim thClean.c
[fsy@localhost process]$ gcc thClean.c -o thclean -lpthread
[fsy@localhost process]$ ./thclean
welcome enter the func1!
clean is called by the first time call! //second已经被pop
welcome enter the func2!
clean is called by the second time call!
clean is called by the first time call!
[fsy@localhost process]$

转载于:https://www.cnblogs.com/askDing/p/5111431.html

内容概要:本文探讨了在MATLAB/SimuLink环境中进行三相STATCOM(静态同步补偿器)无功补偿的技术方法及其仿真过程。首先介绍了STATCOM作为无功功率补偿装置的工作原理,即通过调节交流电压的幅值和相位来实现对无功功率的有效管理。接着详细描述了在MATLAB/SimuLink平台下构建三相STATCOM仿真模型的具体步骤,包括创建新模型、添加电源和负载、搭建主电路、加入控制模块以及完成整个电路的连接。然后阐述了如何通过对STATCOM输出电压和电流的精确调控达到无功补偿的目的,并展示了具体的仿真结果分析方法,如读取仿真数据、提取关键参数、绘制无功功率变化曲线等。最后指出,这种技术可以显著提升电力系统的稳定性与电能质量,展望了STATCOM在未来的发展潜力。 适合人群:电气工程专业学生、从事电力系统相关工作的技术人员、希望深入了解无功补偿技术的研究人员。 使用场景及目标:适用于想要掌握MATLAB/SimuLink软件操作技能的人群,特别是那些专注于电力电子领域的从业者;旨在帮助他们学会建立复杂的电力系统仿真模型,以便更好地理解STATCOM的工作机制,进而优化实际项目中的无功补偿方案。 其他说明:文中提供的实例代码可以帮助读者直观地了解如何从零开始构建一个完整的三相STATCOM仿真环境,并通过图形化的方式展示无功补偿的效果,便于进一步的学习与研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值