当前位置: 首页 > news >正文

Linux软件编程-线程(2)

1.多线程的创建

#include <stdio.h>
#include <pthread.h>typedef int u32;
//将一个函数指针类型重命名成PFUN_t类型
typedef void *(*PFUN_t)(void *);void *main_ctl(void *arg)
{while (1){printf("主控模块正在工作...\n");sleep(1);}
}void *get_cmd(void *arg)
{while (1){printf("获取指令模块正在工作...\n");sleep(1);}
}void *ctl_cmd(void *arg)
{while (1){printf("执行指令模块正在工作...\n");sleep(1);}
}void *get_pic(void *arg)
{while (1){printf("图像采集模块正在工作...\n");sleep(1);}
}void *send_pic(void *arg)
{while (1){printf("图像发送模块正在工作...\n");sleep(1);}
}
int main(int argc, const char *argv[])
{pthread_t tid[5];//	void *(*pfun)(void *);       //函数指针  //指针名称:pfun
//	void *(*pfuns[5])(void *) = {main_ctl, get_cmd};   //函数指针数组  //数组名:pfunint a[10];PFUN_t tasks[5] = {main_ctl, get_cmd, ctl_cmd, get_pic, send_pic};for (int i = 0; i < 5; i++){pthread_create(&tid[i], NULL, tasks[i],NULL);}while (1){printf("xxxxx\n");sleep(1);}pthread_join();/*pthread_create(&tid[0], NULL, main_ctl, NULL);pthread_create(&tid[1], NULL, get_cmd, NULL);pthread_create(&tid[2], NULL, ctl_cmd, NULL);pthread_create(&tid[3], NULL, get_pic, NULL);pthread_create(&tid[4], NULL, send_pic, NULL);*/for (int i = 0; i < 5; i++){pthread_join(tid[i], NULL);}return 0;
}

2..线程的消亡

(1)线程退出

1)在线程任务函数中使用return结束线程
2)pthread_exit(NULL)退出线程;

void pthread_exit(void *retval);
功能:退出一个线程任务
参数:
retval:向回收的线程传递的参数的地址
NULL: 表示不传递参数

(2)线程回收

int pthread_join(pthread_t thread, void **retval);
功能:阻塞等待回收线程资源空间
参数:
thread:要回收的线程ID
retval:用来保存线程退出时传递的参数
NULL: 不接收传递的参数
返回值:
成功:0
失败:-1

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>//次线程
void *task(void *arg)
{int i = 0;while (1){if (++i == 10){char str[] = {"thread over!"};//	return "hello";pthread_exit(NULL); // return NULL;}printf("I am thread : tid = %ld\n", pthread_self());sleep(1);}printf("hello world\n");return NULL;
}int main(int argc, const char *argv[])
{//主进程、主线程pthread_t tid;int ret = pthread_create(&tid, NULL, task, NULL);if (ret !=0){printf("pthread_create error\n");return -1;}//void *retval;pthread_join(tid, NULL);//printf("retval -> %s\n", (char *)retval);return 0;
}

线程回收策略:

1. 分离属性的线程:不需要回收,由操作系统回收。(没有空闲的线程可帮忙回收时)
2. 非分离属性的线程:pthread_join()阻塞回收

线程属性:

1. 分离属性:不需要被其他线程回收的线程称为分离属性得到线程,将来会被操作系统所回收
int pthread_detach(pthread_t thread);
功能:将线程设置成分离属性的线程
2. 非分离属性:可以被其他线程回收或者结束的线程,称为非分离属性的线程
(默认属性:非分离属性)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>//次线程
void *task(void *arg)
{
//	printf("I am thread : tid = %ld\n", pthread_self());
}int main(int argc, const char *argv[])
{//主进程、主线程pthread_t tid;int i = 0;	while (1){int ret = pthread_create(&tid, NULL, task, NULL);if (ret !=0){printf("pthread_create error\n");return -1;}pthread_detach(tid);i++;printf("i = %d\n", i);}return 0;
}

返回值内存管理规则

静态/全局数据:

可以安全返回,因为生命周期是整个程序运行期间

字符串常量:

可以安全返回,如return "hello";

动态分配内存:

可以返回,但需要确保后续有释放机制

通常由接收线程负责释放

禁止返回:

自动局部变量(函数内非静态变量)

线程栈上的变量

3.线程间的通信

全局变量通信:

线程间互斥机制:

临界资源:多个线程可以同时访问的资源称为临界资源:比如,全局变量、共享内存区域等
多个线程在访问临界资源时,存在资源竞争问题。

如何解决资源竞争问题:
互斥机制:多个线程访问临界资源时,具有排他性访问的机制(一次只允许一个线程对该临界资源进行访问)。
互斥锁----->解决资源竞争问题。

实现步骤:
1. 创建互斥锁:pthread_mutex_t
2. 初始化互斥锁:pthread_mutex_init();
3. 加锁:int pthread_mutex_lock(pthread_mutex_t *mutex);
4. 解锁:int pthread_mutex_unlock(pthread_mutex_t *mutex);
5. 销毁锁:int pthread_mutex_destroy(pthread_mutex_t *mutex);

 int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);

功能:初始化互斥锁
参数:
mutex:锁对象地址
attr:锁的属性 (NULL:默认属性)
返回值:
成功:0
失败:-1

#include <stdio.h>
#include <pthread.h>int num_g = 0;
pthread_mutex_t mutex;void *task1(void *arg)
{pthread_mutex_lock(&mutex);for(int i = 0; i < 100000; ++i){num_g += 1;printf("num_g = %d\n",num_g);}pthread_mutex_unlock(&mutex);
}void *task2(void *arg)
{pthread_mutex_lock(&mutex);for(int i = 0; i < 100000; ++i){num_g += 1;printf("num_g = %d\n", num_g);}pthread_mutex_unlock(&mutex);
}int main(int argc, char const *argv[])
{pthread_t tid[2];pthread_mutex_init(&mutex, NULL);pthread_create(&tid[0], NULL, task1, NULL);pthread_create(&tid[1], NULL, task2, NULL);pthread_join(tid[0], NULL);pthread_join(tid[1], NULL);pthread_mutex_destroy(&mutex);return 0;
}

4.函数指针的使用

1. 定义
返回值类型 (*指针名称)(形参表);
void *(*pfun)(void *);

2. 函数指针初始化
返回值类型 (*指针名称)(形参表)=函数的入口地址;

    void *(*pfun)(void *) = main_ctl;

3. 函数指针赋值
函数指针名称=函数的入口地址;
void *(*pfun)(void *) = NULL;
pfun = main_ctl;

4. 函数指针怎么使用
函数名(实参表);
函数指针(实参表);

5. 函数指针的数组:保存多个函数指针
返回值类型 (*数组名称[n])(形参表);
void *(*pfun[5])(void *);

http://www.dtcms.com/a/335060.html

相关文章:

  • Python训练营打卡 DAY 38 Dataset和Dataloader类
  • 《代码重生:杨蓉与62.webp》
  • PowerShell中搜索文件夹
  • 国内代理IP在SEO行业中的应用
  • 云安全 - The Big IAM Challenge
  • 低代码平台能力框架:可复用组件与复杂业务的实现机制
  • 现金流预测模型:12个月精准计算指南
  • 嵌入式硬件篇---电感本质
  • Tomcat架构深度解析:从Server到Servlet的全流程揭秘
  • 【数据分享】上市公司供应链成本分摊数据(2007-2024)
  • 使用Python的defaultdict处理字典中的缺失键
  • C++设计模式:面向对象设计原则
  • 肖臻《区块链技术与应用》第20-22讲 - 以太坊难度调整、权益证明和智能合约
  • Java:File类、递归、字符集、IO流体系及Commons-io框架
  • MySQL锁机制:悲观锁VS乐观锁详解
  • 关于“卷积“
  • 《智能体(Agent)速记指南》
  • Linux进程概念(四)环境地址变量
  • 算法第四十六天:动态规划part13(第九章)
  • STM32 软件I2C读写MPU6050
  • Redis入门与背景详解:构建高并发、高可用系统的关键基石
  • Linux系统编程练习、作业
  • Flink Stream API 源码走读 - 总结
  • 差分约束.
  • 腾讯混元大模型:实现3D打印产品生成的自动化平台
  • [Python 基础课程]继承
  • [Linux] RAID存储技术
  • 【102页PPT】电子行业数字化解决方案(附下载方式)
  • 容器化部署:用Docker封装机器翻译模型与服务详解
  • 服务器可以ping通,但部署的网站打不开