【linux服务器编程学习】10.多线程编程

2023-11-12

linux中的线程

线程是linux中完成一个独立任务的完整执行序列,即一个可调度的实体。根据运行环境,可分为内核线程和用户线程,分别由内核和程序线程库调度。关于linux多线程编程,需要掌握怎么创建和结束线程,怎么读取和设置线程属性,线程同步方式等。

创建和结束线程

  • 线程的创建
#include<pthread.h>
int pthread_create(pthread_t* thread,const pthread_attr_t* attr,void *(start_routline)(void*),void* arg);
thread 是新线程的标识符。
attr用于设置新线程的属性。
start_routline 设置线程将运行的函数
arg是线程运行函数的参数。
成功返回0,失败返回错误码
  • 线程的结束
    pthread_exit 函数通过retval参数向线程的回收者传递其退出信息。
#include<pthread.h>
void pthread_exit(void* retval);

pthread_join 用于回收线程。

#include<pthread.h>
int pthread_join(pthread_t thread,void ** retval);
thread是目标线程的标识符,retval是目标线程返回的退出信息。
成功返回0,失败返回错误码。
该函数会一直阻塞,直到被回收的线程结束。

pthread_cancel立即取消线程。

#include<pthread.h>
int pthread_cancel(pthread_t thread);
thread是线程标识符
成功返回0,失败返回错误码

接收到取消请求的目标线程可以决定是否允许被取消以及如何取消。

#include<pthread.h>
int pthread_setcancelstate(int state,int *oldstate);
int pthread_setcanceltype(int type,int *oldtype);
第一个参数用于设置线程的取消状态(是否允许取消)和取消类型(如何取消)
第二个参数用于记录原来的取消状态和取消类型。

state取值:
PTHREAD_CANCEL_ENABLE  允许线程被取消默认状态
PTHREAD_CANCEL_DISABLE  禁止线程被取消,收到请求取消会挂起,知道允许取消
type取值:
PTHREAD_CANCEL_ASYNCHRONOUS:随时可以被取消
PTHREAD_CANCEL_DEFERRED:允许目标线程推迟行动

POSIX信号量

linux的信号量API有两组,在进程间通信的是System V IPC信号量,用于线程间同步的是POSIX信号量。这两组信号量接口类似,但是不保证能互换。

#include<semphore.h>
int sem_init(sem_t* sem,int pshared,unsigned int value);
初始化一个未命名的信号量,pshared 指定信号量类型,为0表示只能在当前进程中使用,否则在多进程共享,value表示信号量初始值
int semdestroy(sem_t sem);
销毁信号量
int sem_wait(sem_t* sem);
信号量值减1,如变为0则阻塞。
int sem_trywait(sem_t* sem)
非阻塞的sem_wait,如-1后为0,则立即返回-1.
int sem_post(sem_t * sem);
信号量值加1,如阻塞就唤醒

互斥锁

互斥锁可以保护临界区代码段,确保独占式访问。当进入临界区,需要获得互斥锁并加锁,当离开临界区,需要对互斥锁解锁,唤醒其他等待该互斥锁的线程。

#include<pthread.h>
int pthread_mutex_init(pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr);
初始化互斥锁,mutexattr通常设为NULL

int pthread_mutex_destroy(pthread_mutex_t* mutex);
销毁互斥锁

int pthread_mutex_lock(pthread_mutex_t* mutex);
互斥锁加锁

int pthread_mutex_trylock(pthread_mutex_t* mutex);
互斥锁非阻塞加锁

int pthread_mutex_unlock(pthread_mutex_t* mutex);
互斥锁解锁

成功返回0,失败返回错误码

条件变量

如果说互斥锁用于同步线程对共享数据的访问,条件变量机制用于在线程之间同步共享数据的值。
条件变量提供一种线程间通知机制,当某个共享数据到达某个值时,唤醒等待这个共享数据的值。

#include<pthread.h>
int pthread_cond_init(pthread_cond_t* cond,const pthread_condattr_t* cond_attr)
初始化条件变量,cond_attr参数指定条件变量的属性,通常设为NULL
int pthread_cond_destroy(pthread_cond_t* cond);
销毁一个条件变量,销毁一个正在等待的条件变量将返回EBUSY
int pthread_cond_broadcast(pthread_cond_t* cond);
以广播的方式,唤醒所有等待目标条件变量的线程
int pthread_cond_signal(pthread_cond_t* cond);
唤醒一个等待目标条件变量的线程
int pthread_cond_wait(pthread_cond_t* cond,pthread_mutex_t* mutex);
用于等待目标条件变量,mutex参数用于保护条件变量,需要确保存在且上锁。

成功返回0,否则返回错误码。

可重入函数

如果一个函数能被多个线程同时调用且不发生竞态条件,成为线程安全的,或者说是可重入函数。linux库函数只有一小部分是不可重入的。很多不可重入函数被提供了可重入版本,在原函数名尾部加_r。

线程和进程

如果一个多线程程序的某个线程调用了fork函数,新创建的子进程不会自动创建和父进程同样数量的线程。子进程只有一个执行线程,是调用fork那个线程的完整复制,并且子进程会自动继承父进程中互斥锁、条件变量的状态,但是不知道是否上锁,如果这时再加锁就会导致死锁。

pthread提供了一个专门的函数pthread_atfork,确保fork调用后父进程和子进程都有一个清楚的状态。

线程和信号

每个线程都可以独立的设置信号掩码,但是多线程环境下应该使用pthread_sigmask设置信号掩码,与sigprocmask参数和返回值完全相同。

由于进程中的所有线程共享进程的信号和信号处理函数。线程库将根据线程掩码决定把信号发送给哪个具体线程,如果在每个线程中单独设置信号掩码容易出错。

应该定义一个专门的线程处理信号。首先在主线程创建子线程之前就设置好信号掩码,让子线程继承这个信号掩码,然后再某个线程中调用sigwait等待信号并处理。

此外还可以使用pthread_kill 明确的将一个信号发送给指定线程。

后记

机遇固然是好的,但是我们不能只依赖机遇,即便它来了,你也无法保证能抓住它。不如保持长期的计划,做好充足的准备,最后自己创造机遇。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【linux服务器编程学习】10.多线程编程 的相关文章

随机推荐

  • 什么是面向对象思想

    面向对象是一种思想 是基于面向过程而言的 就是说面向对象是将功能等通过对象来实现 将功能封装进对象之中 让对象去实现具体的细节 这种思想是将数据作为第一位 而方法或者说是算法作为其次 这是对数据一种优化 操作起来更加的方便 简化了过程 面向
  • 人工智能作业homework2--------A*算法解决八数码

    1 启发式搜索算法A 启发式搜索算法A 一般简称为A算法 是一种典型的启发式搜索算法 其基本思想是 定义一个评价函数f 对当前的搜索状态进行评估 找出一个最有希望的节点来扩展 评价函数的形式如下 f n g n h n 其中n是被评价的节点
  • 全网最详细中英文ChatGPT接口文档(五)30分钟快速入门ChatGPT——手把手示例教程:如何建立一个人工智能回答关于您的网站问题,小白也可学

    30分钟开始使用ChatGPT Models模型 How to build an AI that can answer questions about your website 如何建立一个人工智能 回答有关您的网站的问题 Getting
  • 整理了27个Python人工智能库,建议收藏

    为了大家能够对人工智能常用的 Python 库有一个初步的了解 以选择能够满足自己需求的库进行学习 对目前较为常见的人工智能库进行简要全面的介绍 1 Numpy NumPy Numerical Python 是 Python的一个扩展程序库
  • ssd m.2接口详解

    ssd有两种接口 一种是sata 一种是m 2 这里主要深入讲解一下m 2接口的ssd 1 ssd 尺寸与规格 我们在买ssd的时候 商家都会说什么ssd是2280还是2242规格的 这里的规格实际上就是代表的ssd的大小 M 2模组的尺寸
  • pytrch手写数字识别

    使用Pytorch实现手写数字识别 目标 知道如何使用Pytorch完成神经网络的构建 知道Pytorch中激活函数的使用方法 知道Pytorch中torchvision transforms中常见图形处理函数的使用 知道如何训练模型和如何
  • Unity:利用 射线Ray 检测物体

    利用 射线Ray 检测物体 Unity射线 Ray 是通过发射一条射线来检测碰撞体或触发器 不带碰撞器组件的物体时无法检测的 可以在物理设置里取消检测触发器 Edit Project Setting Physics Physics2D Ph
  • Spring Boot中的Dozer和MapStruct比较

    Spring Boot中的Dozer和MapStruct比较 在Java开发中 数据对象之间的转换是一个常见的任务 Spring Boot作为一个流行的Java框架 提供了多种方式来处理对象之间的转换 两个常用的工具是Dozer和MapSt
  • call、apply、bind方法详解

    1 每个函数都包含两个非继承而来的方法 call 方法和apply 方法 2 相同点 这两个方法的作用是一样的 只是传参方式不一样而已 call 方法使用 window msg 1 document msg 2 var log msg 3
  • springboot 如何修改控制台输出的图案

    如图 操作步骤 1 在项目的resource文件夹下 新建一个文件命名为banner txt 2 进入网站 http patorjk com software taag p display h 0 v 0 f Big t SpringBoo
  • Spring WebSocket通信应用

    文章目录 前言 一 客户端 服务端双向通信交互图 二 项目说明 1 引入包 2 项目各模块说明 问题 参考 前言 本文章主要记录项目客户端 服务端双向通信解决方案 基于Spring WebSocket架构实现双向数据通信 以及项目实际应用中
  • 【SQLAlchemy】第二篇——连接失效及连接池

    一 背景 为了节约资源 MySQL会对建立的连接进行监控 当某些连接处于不活跃状态的时间超过一个阈值时 则关闭它们 用户可以执行show variables like wait timeout 来查看这个阈值 可以看到 在默认的情况下 这个
  • 04-8_Qt 5.9 C++开发指南_QTableWidget的使用

    文章目录 1 QTableWidget概述 2 源码 2 1 可视化UI设计 2 2 程序框架 2 3 qwintspindelegate h 2 4 qwintspindelegate cpp 2 5 mainwindow h 2 6 m
  • VisionWorks快速入门--Graph Mode

    VisionWorks快速入门 Graph Mode 从立即模式过渡到图形模式 1 创建新节点 2 向GraphModestabilizer类添加新字段和函数 3 初始化字段 4 执行算法的迭代 5 Release objects 结果 本
  • 解决科研人痛点的大突破:Zotero 6.0 版有哪些亮点?

    痛点 翻了翻日记 发现我第一次使用 Zotero 文献管理器的时间 是 2008 年 12 月 19 日 这中间曾经因为论文写作需要处理中文文献等原因 若干次切换过其他的文献管理器 包括 NoteExpress 和 Mendeley 等 几
  • IIS站点发布log

    1 启用IIS服务 2 打开IIS管理界面 3 添加站点 4 填写站点信息 1 物理路径为发布的log文件目录 2 填写IP地址和端口 5 发布的log文件设置权限 添加Everyone用户 并设置权限 6 启动站点 浏览器访问 此时出错
  • city_picker改造-------五级城市联动控件

    这几天做项目 需要用到城市控件 网上找了个样式不错的控件 基于bootstrap的 具体用法可以参照https blog csdn net bsw451926392 article details 78886965 但是我这边需要精确到村级
  • vscode的vue中出现很多红色波浪线解决办法

    vscode的vue中出现很多红色波浪线 看上去就很烦 如下所示 这么看呢 代码没什么问题 为什么有那么多红色波浪线呢 其实出现这个的原因是代码和vetur插件的格式不对应 解决办法 1 严格遵循vetur的格式去写 不过麻烦 2 关闭ve
  • 区块链系统面临哪些风险以及有哪些防范措施

    区块链是涉及多方的开放系统 早期的应用又与虚拟加密货币相关 由此使得区块链系统所内含的和面对的风险得以暴露 同时各种安全措施也得以被及时使用和验证 但区块链在真实世界的大规模应用尚未展开 因此区块链所内含以及面临的风险暴露尚不完全 预防措施
  • 【linux服务器编程学习】10.多线程编程

    linux中的线程 线程是linux中完成一个独立任务的完整执行序列 即一个可调度的实体 根据运行环境 可分为内核线程和用户线程 分别由内核和程序线程库调度 关于linux多线程编程 需要掌握怎么创建和结束线程 怎么读取和设置线程属性 线程