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

线程的创建

1. 多线程常用函数

1.1 创建一条新线程pthread_create

在这里插入图片描述
对此函数使用注意以下几点:

  • 线程例程指的是:如果线程创建成功,则该线程会立即执行的函数。
  • POSIX线程库的所有API对返回值的处理原则一致:成功返回0,失败返回错误码errno.
  • 线程属性如果为NULL, 则会创建一个标准属性的线程,线程的属性非常多,有关线程的属性待研究

PTHREAD_CREATE_DETACHED 分离线程没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。
PTHREAD _CREATE_JOINABLE 线程的默认属性是非分离状态,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算。

1.2 线程的退出

线程跟进程类似,在缺省的状态下退出之后,会变成僵尸线程,并且保留退出值。其他线程可以通过相关 API 接合该线程——使其资源被系统回收,如果愿意的话还可以顺便获取其退出值。下面是相关 API:
在这里插入图片描述
在这里插入图片描述
线程执行完后如果不join的话,线程的资源会一直得不到释放而导致内存泄漏。
用上述函数需要注意以下几点:

  • 如果线程退出时没有退出值,那么 retval 可以指定为 NULL。
  • pthread_join( )指定的线程如果尚在运行,那么他将会阻塞等待。
  • pthread_tryjoin_np( )指定的线程如果尚在运行,那么他将会立即出错返回。

在某个时刻不能等某个线程“自然死亡”,而需要勒令其马上结束,此时可
以给线程发送一个取消请求,让其中断执行而退出。用到如下 API:
在这里插入图片描述

1.3 pthread_join/pthread_exit的用法解析

pthread_join 用于等待一个线程的结束,也就是主线程中要是加了这段代码,就会在加代码的位置卡主,直到这个线程执行完毕才往下走。
pthread_exit 用于强制退出一个线程(非执行完毕退出),一般用于线程内部。

一般都是 pthread_exit 在线程内退出,然后返回一个值。这个时候就跳到主线程的 pthread_join了(因为一直在等你结束),这个返回值会直接送到pthread_join,实现了主与分线程的通信。

2. 线程资源回收pthread_detach()函数的使用

每一个线程在任何情况,要么是可结合的状态(joinable),要么是可分离的状态(detached)。
两个函数的原型:

int pthread_join(pthread_t tid, void ** pthread_return);
int pthread_detach(pthread_t tid);

当线程运行结束后,最后显示的调用被回收。这样就出现两种回收方式。

  1. pthread_join 是一个阻塞函数,调用方会阻塞到 pthread_join 所指定的tid的线程结束后才被回收,但是在此之前,调用方是霸占系统资源的。
  2. pthread_detach,不会阻塞,调用它后,线程运行结束后会自动释放资源。
  3. 可分离的状态属性可以在pthread_create 时指定(线程属性),或在线程创建后在线程中pthread_detach自己, 如:pthread_detach(pthread_self()),将状态改为可分离的状态状态,确保资源的释放。或者将线程置为 joinable,然后适时调用pthread_join.

其实简单的说就是在线程函数头加上 pthread_detach(pthread_self())的话,线程状态改变,在函数尾部直接 pthread_exit线程就会自动退出。省去了给线程擦屁股的麻烦

PS:一个可结合线程在运行结束后,若没有调用 pthread_join,会进入一个类似zombie process 的状态,也就是系统中还有一些资源没有回收。需要pthread_join 来回收这些资源。(这就类似进程操作中的waitpid函数)线程在创建时默认的状态是 joinable, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process(僵尸进程),即还有一部分资源没有被回收(退出状态码),所以创建线程者应该 pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid),这样不会导致系统越用越慢的现象。
但是 pthread_join(pthread_id) 函数是阻塞函数,在调用pthread_join(pthread_id)后,如果该线程 没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当 主线程 为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用 pthread_join 而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码

pthread_detach( pthread_self());
或者父线程调用
pthread_detach(thread_id);(非阻塞,可立即返回)

这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。
在嵌入式系统中,如果某些线程要伴随系统一直运行下去,该种情况下是否采用该该函数进行回收,没有什么价值。

3. 代码实例

/** pthread_join()阻塞回收资源*/
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void *thread1_func(void *arg)
{int n;    for (n = 0; n < 30; n++) {sleep(1);printf("AAAAAAAAAA\n");}pthread_exit(NULL);//return NULL;
}void *thread2_func(void *arg)
{int n;for (n = 0; n < 30; n++) {sleep(1);printf("BBBBBBBBBB\n");}return NULL;
}int main(int argc, char *argv[])
{pthread_t tid1, tid2;if (pthread_create(&tid1, NULL, thread1_func, NULL) != 0) {perror("main: pthread_create thread_1 failed");return 1;} else {printf("main: pthread_create thread_1 succeed!\n");}if (pthread_create(&tid2, NULL, thread2_func, NULL) != 0) {perror("main: pthread_create thread_2 failed");return 1;} else {printf("main: pthread_create thread_2 succeed!\n");}if (pthread_join(tid1, NULL) != 0) {perror("main: pthread_join thread_1 failed");}if (pthread_join(tid2, NULL) != 0) {perror("main: pthread_join thread_2 failed");}printf("main is exiting.\n");return 0;
}

以下为一个多线程服务模型

/** pthread_detach() 自动释放资源资源*/
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>/*** @brief 接收客户端发来的消息*        若客户端发来正常的消息便广播给其他应用,如客户端退出则删除对应客户端节点* @param ags * @return void* */
void *routine(void *ags) 
{//获取自己的TID, 进而分离自己;将来退出时立即释放资源pthread_detach(pthread_self());int connfd = (int)(*((int*)ags));char buf[SIZE];while (1){bzero(buf, SIZE);//1. 关闭客户端或退出if (Read(connfd, buf, SIZE) == 0 || //read读取的是一个管道,如果对端关闭连接返回0!strcmp(buf, "quit\n")) {del_client(connfd);break;}//2. 转发客户端的信息给到系统的其他客户端节点broad_cast(buf, connfd);}pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{if (argc != 2) //外部动态输入端口号{printf("Usage: %s <PORT>\n", argv[0]);exit(0);}//TCP 创建套接字int sockfd = Socket(AF_INET, SOCK_STREAM, 0); //AF_INET:IPV4X协议 SOCK_STREAM:流式套接字struct sockaddr_in seraddr, cliaddr;socklen_t len = sizeof(seraddr);bzero(&seraddr, len);seraddr.sin_family = AF_INET;seraddr.sin_port = htons(atoi(argv[1]));/*自动获取网卡地址*/seraddr.sin_addr.s_addr=htonl(INADDR_ANY);//绑定地址Bind(sockfd, (struct sockaddr *)&seraddr, len);//设置监听套接字Listen(sockfd, 3); //在linux中同时发起连接请求个数为3+4=7个while (1){//持续等待对方连接,设置连接套接字,连接未建立完成处于阻塞中len = sizeof(cliaddr);int connfd = Accept(sockfd, (struct sockaddr *)&cliaddr, &len); //此处如需要保存客户端点地址信息,用 cliaddr接收,若不需要则为NULLchar peeraddr[50];bzero(peeraddr, 50);printf("new connection: %s:%hu\n", inet_ntop(AF_INET, &cliaddr.sin_addr, peeraddr, 50), ntohs(cliaddr.sin_port)); // 打印客户端的IP地址和端口pthread_t tid;pthread_create(&tid, NULL, routine, (void *)&connfd); }Close(sockfd);return 0;
}

相关文章:

线程的创建

1. 多线程常用函数 1.1 创建一条新线程pthread_create 对此函数使用注意以下几点&#xff1a; 线程例程指的是&#xff1a;如果线程创建成功&#xff0c;则该线程会立即执行的函数。POSIX线程库的所有API对返回值的处理原则一致&#xff1a;成功返回0&#xff0c;失败返回错误…...

分布式之Paxos共识算法分析

写在前面 分布式共识是分布式系统中的重要内容&#xff0c;本文来一起看下&#xff0c;一种历史悠久&#xff08;1998由兰伯特提出&#xff0c;并助其获得2003年图灵奖&#xff09;的实现分布式共识的算法Paxos。Paxos主要分为两部分&#xff0c;Basic Paxos和Multi-Paxos,其中…...

35岁测试工程师,面临中年危机,我该如何自救...

被辞的原因 最近因故来了上海&#xff0c;联系上了一位许久不见的老朋友&#xff0c;老王&#xff1b;老王和我是大学同学&#xff0c;毕业之后他去了上海&#xff0c;我来到广州。因为我们大学专业关系&#xff0c;从12年毕业以后我们从事着相同的职业&#xff0c;软件自动化…...

时间轮算法概念

概述 在一些中间件中我们经常见到时间轮控制并发和熔断。 那么这个时间轮具体是什么呢&#xff0c;又是怎么使用的呢。 简介 其实时间轮可以简单的理解成我们日常生活中的时钟。 时钟里的指针一直在不停的转动&#xff0c;利用这个我们可以实现定时任务&#xff0c;目前lin…...

[SCTF2019]babyre 题解

对未来的真正慷慨&#xff0c;是把一切献给现在。 ——加缪 目录 1.查壳 2.处理花指令&#xff0c;找到main函数 这一操作过程可以参考下面的视频&#xff1a; 3.静态分析第一部分,psword1 4.静态分析第二部分,psword2 5.静态分析第五部分&#xff0c;psword3 6.根据ps…...

全志H3系统移植 | 移植主线最新uboot 2023.04和kernel 6.1.11到Nanopi NEO开发板

文章目录 环境说明uboot移植kernel移植rootfs移植测试环境说明 OS:Ubuntu 20.04.5 LTSGCC:arm-none-linux-gnueabihf-gcc 10.3.0编译器下载地址:Downloads | GNU-A Downloads – Arm Developer uboot移植 当前最新版本v2023.04-rc2下载地址:https://github.com/u-boot/u-…...

vue项目第四天

使用elementui tabplane组件实现历史访问记录组件的二次封装<el-tabs type"border-card"><el-tab-pane label"用户管理">用户管理</el-tab-pane><el-tab-pane label"配置管理">配置管理</el-tab-pane><el-tab-…...

「C语言进阶」数据内存的存储

&#x1f680;&#x1f680;&#x1f680;大家觉不错的话&#xff0c;就恳求大家点点关注&#xff0c;点点小爱心&#xff0c;指点指点&#x1f680;&#x1f680;&#x1f680; 目录 &#x1f430;数据类型的介绍 &#x1f430;类型的意义 &#x1f430;数据类型的基本归类…...

面试必问:进程和线程的区别(从操作系统层次理解)

1.什么是进程&#xff1f;为什么要有进程&#xff1f; 进程有一个相当精简的解释&#xff1a;进程是对操作系统上正在运行程序的一个抽象。 这个概念确实挺抽象&#xff0c;仔细想想却也挺精准。 我们平常使用计算机&#xff0c;都会在同一时间做许多事&#xff0c;比如边看…...

ModuleNotFoundError: No module named ‘apex‘与 error: legacy-install-failure

ModuleNotFoundError: No module named ‘apex’ ModuleNotFoundError: No module named apex 表示 Python 在搜索模块时无法找到名为 apex 的模块。这通常是因为您没有安装 apex 模块或安装不正确。 apex 是一个针对混合精度训练和优化的 PyTorch 扩展库&#xff0c;您可以通过…...

Python3 VScode 配置

Python3 VScode 配置 在上一章节中我们已经安装了 Python 的环境&#xff0c;本章节我们将介绍 Python VScode 的配置。 准备工作&#xff1a; 安装 VS Code 安装 VS Code Python 扩展 安装 Python 3 安装 VS Code VSCode&#xff08;全称&#xff1a;Visual Studio Code&…...

VMware 修复了三个身份认证绕过漏洞

Bleeping Computer 网站披露&#xff0c;VMware 近期发布了安全更新&#xff0c;以解决 Workspace ONE Assist 解决方案中的三个严重漏洞&#xff0c;分别追踪为 CVE-2022-31685&#xff08;认证绕过&#xff09;、CVE-2022-31686 &#xff08;认证方法失败&#xff09;和 CVE-…...

实现一个简单的Database10(译文)

GreatSQL社区原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本&#xff0c;使用上与MySQL一致。作者&#xff1a; 花家舍文章来源&#xff1a;GreatSQL社区原创 前文回顾 实现一个简单的Database系列 译注&#xff1a;csta…...

CTF-取证题目解析-提供环境

一、安装 官网下载&#xff1a;Volatility 2.6 Release 1、将windows下载的volatility上传到 kali/home 文件夹里面 3、将home/kali/vol刚刚上传的 移动到use/sbin目录里面 mv volatility usr/local/sbin/ 切换到里面 cd /usr/local/sbin/volatility 输入配置环境echo $PAT…...

计算机基础 | 网络篇 | TCP/IP 四层模型

前沿&#xff1a;撰写博客的目的是为了再刷时回顾和进一步完善&#xff0c;其次才是以教为学&#xff0c;所以如果有些博客写的较简陋&#xff0c;是为了保持进度不得已而为之&#xff0c;还请大家多多见谅。 一、OSI 七层模型 参考文章&#xff1a;OSI 和 TCP/IP 网络分层模型…...

实时数据仓库

1 为什么选择kafka? ① 实时写入&#xff0c;实时读取 ② 消息队列适合&#xff0c;其他数据库受不了 2 ods层 1&#xff09;存储原始数据 埋点的行为数据 (topic &#xff1a;ods_base_log) 业务数据 (topic &#xff1a;ods_base_db) 2&#xff09;业务数据的有序性&#x…...

leetcode 1250. 检查「好数组」

给你一个正整数数组 nums&#xff0c;你需要从中任选一些子集&#xff0c;然后将子集中每一个数乘以一个 任意整数&#xff0c;并求出他们的和。 假如该和结果为 1&#xff0c;那么原数组就是一个「好数组」&#xff0c;则返回 True&#xff1b;否则请返回 False。 示例 1&…...

JDK动态代理和CGLib动态代理的区别

原文网址&#xff1a;JDK动态代理和CGLib动态代理的区别_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java中JDK动态代理和CGLib动态代理的区别。 区别概述 项 JDK动态代理 CGLIB动态代理 接口是否需实现 只能代理实现了接口的类。 可以代理没有实现接口的类。 原理 继承…...

Leetcode.1250 检查「好数组」

题目链接 Leetcode.1250 检查「好数组」 Rating &#xff1a; 1983 题目描述 给你一个正整数数组 nums&#xff0c;你需要从中任选一些子集&#xff0c;然后将子集中每一个数乘以一个 任意整数&#xff0c;并求出他们的和。 假如该和结果为 1&#xff0c;那么原数组就是一个「…...

WMS系统推荐,如何选到适合企业的仓库管理系统

市场上有很多WMS系统&#xff0c;但是现在很多仓库管理系统都在使用WMS系统。那么在选择WMS系统时应该考虑什么呢&#xff1f;明确业务发展特征&#xff0c;准确表达能力目标许多物流企业在选择物流管理系统时&#xff0c;往往会被物流管理系统的整体系统所迷惑&#xff0c;在功…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...