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

【Linux】【应用层】多线程编程

一、线程创建

Linux 中的 pthread_create() 函数用来创建线程,它声明在<pthread.h>头文件中,语法格式如下:

int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine) (void *),void *arg);

各个参数的含义是:

  1. pthread_t *thread:传递一个 pthread_t 类型的指针变量,也可以直接传递某个 pthread_t 类型变量的地址。pthread_t 是一种用于表示线程的数据类型,每一个 pthread_t 类型的变量都可以表示一个线程。
  2. const pthread_attr_t *attr:用于手动设置新建线程的属性,例如线程的调用策略、线程所能使用的栈内存的大小等。大部分场景中,我们都不需要手动修改线程的属性,将 attr 参数赋值为 NULL,pthread_create() 函数会采用系统默认的属性值创建线程。
  3. void *(*start_routine) (void *):以函数指针的方式指明新建线程需要执行的函数,该函数的参数最多有 1 个(可以省略不写),形参和返回值的类型都必须为 void* 类型。void* 类型又称空指针类型,表明指针所指数据的类型是未知的。使用此类型指针时,我们通常需要先对其进行强制类型转换,然后才能正常访问指针指向的数据。

如果该函数有返回值,则线程执行完函数后,函数的返回值可以由 pthread_join() 函数接收。有关 phtread_join()

  1. void *arg:指定传递给 start_routine 函数的实参,当不需要传递任何数据时,将 arg 赋值为 NULL 即可。
    如果成功创建线程,pthread_create() 函数返回数字 0,反之返回非零值。各个非零值都对应着不同的宏,指明创建失败的原因,常见的宏有以下几种:
    EAGAIN:系统资源不足,无法提供创建线程所需的资源。
    EINVAL:传递给 pthread_create() 函数的 attr 参数无效。
    EPERM:传递给 pthread_create() 函数的 attr 参数中,某些属性的设置为非法操作,程序没有相关的设置权限。

以上这些宏都声明在 <errno.h> 头文件中,如果程序中想使用这些宏,需提前引入此头文件。

二、线程通信

在Linux中,多线程通信可以使用许多不同的机制。以下是一些常用的多线程通信方法:

  1. 互斥锁(mutex):互斥锁用于保护共享资源,以便在任何时候只有一个线程可以访问它。当一个线程获得互斥锁后,其他线程将被阻塞,直到该线程释放锁。
  2. 条件变量(condition variable):条件变量用于在线程之间传递信息,因为它们允许一个线程等待另一个线程满足某个条件。当条件变量满足时,线程可以继续执行;否则,线程将被阻塞。
  3. 信号量(semaphore):信号量用于控制对共享资源的访问,但它们可以同时允许多个线程访问资源。信号量具有计数器,当计数器为0时,调用sem_wait()函数的线程将被阻塞,直到另一个线程调用sem_post()函数增加计数器。
  4. 管道(pipe):管道可以用于在进程之间传递数据,也可以用于在线程之间传递数据。在多线程环境中,可以使用匿名管道或命名管道来实现线程之间的通信。
  5. 共享内存(shared memory):共享内存允许多个线程访问同一块内存区域。这种方式是最快的 IPC 方式,但需要开发者自行处理同步问题。

这些机制可以单独或组合使用。例如,互斥锁和条件变量经常一起使用,以便在线程之间保护共享资源并传递信息。在实践中,选择哪种方法通常取决于应用程序的需求,以及性能、可维护性等方面的考虑。

三、示例代码

#include <pthread.h>
#include <iostream>static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t  cond = PTHREAD_COND_INITIALIZER;static int data_ready = 0;
static int data = 0;void* thread_func(void *arg)
{while (1) {pthread_mutex_lock(&lock);while (!data_ready) {pthread_cond_wait(&cond, &lock);}std::cout << "Data received: " << data << std::endl;data_ready = 0;pthread_mutex_unlock(&lock);}
}int main(int argc, char **argv)
{pthread_t tid;pthread_create(&tid, NULL, thread_func, NULL);int input;while (1) {std::cin >> input;pthread_mutex_lock(&lock);data = input;data_ready = 1;pthread_cond_signal(&cond);pthread_mutex_unlock(&lock);}return 0;
}

pthread不是linux下的默认的库,也就是在链接的时候,无法找到phread库中join函数的入口地址,链接会失败。因此需要编译命令时,附加
-lpthread 参数。(-l是L是小写 不是i的大写I) g++ main.cpp -o main -lpthread

http://www.lryc.cn/news/59257.html

相关文章:

  • GameFramework 框架详解之 如何接入热更框架HybridCLR
  • 全国青少年软件编程(Scratch)等级考试二级考试真题2023年3月——持续更新.....
  • HTML2.1列表标签
  • 在 Flutter 多人视频通话中实现虚拟背景、美颜与空间音效
  • Ambari-web 架构
  • 对接百思买Best Buy EDI 的注意事项
  • 2023年郑州重点建设项目名单公布,中创“算力数据中心”项目入选!
  • Pytorch 容器 - 1. Module类介绍
  • 百度墨卡托坐标转化笔记
  • 每日学术速递4.12
  • HarmonyOS/OpenHarmony公司级技术开发团队硬件基本配置清单
  • 新一代信息技术赋能,安科瑞搭建智慧水务体系的新思路
  • 37岁测试工程师被裁,120天没找到工作,无奈...
  • Java容器使用注意点
  • 密文题解(图论+字典树)
  • Baumer工业相机堡盟工业相机如何通过BGAPISDK里的工具函数来计算工业相机的实时帧率(C#)
  • 数据结构与常量(Java)
  • 【LeetCode】剑指 Offer 54. 二叉搜索树的第k大节点 p269 -- Java Version
  • [工具类] post请求 获取request对象, 获取request的请求体(body)参数
  • Golang 多版本安装小工具G
  • day29—选择题
  • day8 互斥锁/读写锁的概念及使用、死锁的避免
  • 2023-04-13 monetdb-str类型变长存储-分析
  • 011:Mapbox GL两种方式隐藏logo和版权,个性化版权的声明
  • 结合PCA降维的DBSCAN聚类方法(附Python代码)
  • 限流:计数器、漏桶、令牌桶 三大算法的原理与实战(史上最全)
  • Redis用于全局ID生成器、分布式锁的解决方案
  • OpenTex 企业内容管理平台
  • 【0基础学爬虫】爬虫基础之数据存储
  • Redis与本地缓存组合使用(IT枫斗者)