一步一步写线程之十六线程的安全退出之一理论分析

一、多线程的开发

多线程的开发,在实际场景中几乎是无法避开的。即使是前端看似没有使用线程,其实在底层的框架中也使用了线程进行了支撑。至少到现在,不管是协程还是其它什么新的编程方式,仍然无法撼动线程的主流地位。
多线程的开发中,各种复杂的场景今天不分析,只分析一种场景,就是多线程的退出,或者说整体程序的安全退出。有过开发经验的可能都遇到过,程序运行的很好,但一退出就崩溃了。甚至还有的遇到过,有些程序无法退出,只能使用一些特殊的手段暴力杀死线程才能退出。这些现象的出现,其实基本上都是多线程的协调机制(同步、通信等)没有做好。
下面就对多线程的安全退出进行分析和说明。

二、线程的运行分析

既然要线程安全的退出,就必须明白线程在运行时的工作环境。知己知彼,百战不殆。下面就分析一下涉及到线程退出时的一些重点:
1、上下文
线程在执行时,会有一些上下文环境,在操作系统里称为context,其中的内容有很多,但其实重点就是堆栈和一些存储的值,这些值包括一些文件句柄和内存等的值。这为线程的恢复提供了依据,如果上下文被破坏,可想而知结果会是什么。
2、资源
线程运行的目的就是了处理各种任务,任务中包括本身分配的资源和系统分配的资源。而多线程之所以被使用,目的就是为了处理任务及任务相关的数据,这些数据大多数的情况下是依赖和被 依赖于其它线程的(一般只有在学习时才会写一些独立的线程逻辑,与其它线程无关)。而这些数据和资源可能要和其它线程共享,也有可能返回给其它线程,甚至有可能让其它线程来负责销毁和回收。
这就出现了一个很明显的问题,如何在退出时保证资源和数据已经完整正确的发出。如果强行退出,外送的数据不正确,(包括不一致,未发送,发送错误等很多情况)会不会产生问题。举一个例子,一个数据库存储的字段,需要A线程处理,然后送给B线程再加工,然后由C线程负责存储,如果其中一个线程意外退出,那么C线程要么无数据可存储,要么是数据有问题。
同样,如果某种情况,程序退出时出现了问题,产生了僵尸进程。那么它就会占用一系列的系统的资源。同样,非安全退出导致一些系统资源未释放,如硬件IO(端口、句柄等)中的相关资源。那么,此时二次启动时程序可能就无法再次安全启动。
3、协调
多线程的开发,一般来说必然会带来线程间的协调调度,这才是多线程复杂的原因。正如很早前就分析的,如果多个线程只是自己搞自己的事情,和其它线程都没关系,那么这不是真正的多线程开发,从某种意义上来讲,它就是单线程开发。
既然涉及到协调,就有一个问题,某个线程的退出以另外一个线程设置某项条件才能退出,如果设置条件的线程意外退出,整个程序可能就无法退出。通常这也是常见的一种多线程退出的问题。
另外,多线程间的同步如果处理不好,则有可能在退出时造成死锁。同样,也可能因为线程退出的无序,导致资源和内存的泄露等等。所以,多线程的退出就是打仗一样,“进攻是很复杂的,但是撤退更复杂,撤退搞不好就会演变成为溃败!”
明白了吧,万物都是相通,就是这个道理。

三、安全退出的机制和方法

明白了多线程在运行时的情况,那么就可以有针对性的处理这些情况,从而保证多线程退出时的安全。下面就上面分析的几个方面提出几个解决思路:
1、等待机制
通过让线程睡眠或者其它的Wait(一般都有超时机制),等待所有的线程完成后,再共同退出。这种方法简单、粗暴,但对一些新手或者说应用场景简单的情况下,不失为一种解决办法。缺点就是延迟太大,可能在某些情况下仍无法正常退出。
2、轮询机制
就是设立一个标志位或者标记状态,由各个线程去反复的查询,如果到达退出的状态,即可退出。这种方法相对简单,但浪费资源且有较大的退出延迟,一般也是在简单或者特定的场景下使用。
3、消息机制
消息机制是通过多线程间消息的有序传递,来保证线程间有序的安全退出。这种方法相对来说更安全也更优雅。但其实现要相对复杂一些,而且不同的OS中消息机制都有所不同,需要开发者要有针对性的去开发。
4、事件机制
事件机制类似于消息机制,同样也很安全。其缺点与消息机制大致相同。另外,如果开发者考虑不足,还有可能陷入死循环或死锁。
针对这些思路,就有了更具体的解决办法:
1、不同的系统与库中对线程的处理有所不同,以标准库和Linux为例,它的线程创建有两种处理方式,一种是deatch方式,一种是join方式。两种方式的处理机制不同,前者主线程退出子线程也就安全的退出而后者则需要等待子线程的退出后整体程序才会退出。不同的机制有着不同的处理方式,这就看实际场景了,如果实际应用子线程中的数据没有什么意义或者对其它线程没什么影响,就可以使用前者。否则就需要使用后者。
而如果使用后者,就需要参考上面的解决思路,使用类sleep,固定量的死循环等等;或者设置状态位(原子变量或普通变量)不断轮询;或者Linux下的信号如SIGINT、SIGTERM等,Windows可以使用WM开头的系列消息;更优雅的可以使用信号量、条件变量、Windows下的Event机制等等。
2、资源的处理
不管是句柄还是内存亦或什么其它资源,简单一些还好说,一般不会有什么问题。但是多了后如何处理?首推当然是RAII,就是为了解决这类问题的。如果不想使用RAII,也可以利用损害集中管理原则,将资源的处理交到指定的对象中,集中处理。

四、总结

其实多线程如此,多进程大抵亦也如此!只不过目前来看写多进程的已经非常少了。总结到最后,多线程的安全退出只有一条原则,就是让每个线程自己正常退出,而不是暴力打断它的执行。只要贯彻了这一原则,就不会出现多线程退出的各种异常问题。
可是,实际的场景复杂又多变,有的时候确实无法等待所有的线程正常的退出,这就需要开发者自己根据情况进行取舍。有舍才有得,亘古不变的道理!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/481402.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Socket编程(TCP/UDP详解)

前言:之前因为做项目和找实习没得空,计算机网络模块并没有写成博客,最近得闲了,把计算机网络模块博客补上。 目录 一,UDP编程 1)创建套接字 2)绑定端口号 3)发送与接收数据 4&…

虚拟机VMware安装OpenWrt镜像

前提已经安装VMware Workstation Pro,我使用的是VM16 一.下载OpenWrt系统固件 固件有很多种,我选择下面这个链接的固件: Index of /releases/23.05.3/targets/x86/64/ 二.把固件转换成虚拟机能识别的格式 转换工具下载地址:https://www.starwindsoft…

【Canvas与雷达】点鼠标可暂停金边蓝屏雷达显示屏

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>点鼠标可暂停金边蓝屏雷达显示屏 Draft1</title><style typ…

计算机编码存储+char占用空间+final作用

内存中存储的是对应的编码&#xff0c;与对应的形状库一起能够在显示器显示出来对应的字符。 磁盘中存储的是文件信息。 内存中存储的是变量&#xff08;虽然也是在磁盘里&#xff0c;等到使用的时候再调入进来&#xff09;。 因为编码实质就是二进制串&#xff0c;所以也可以比…

vue3项目搭建-6-axios 基础配置

axios 基础配置 安装 axios npm install axios 创建 axios 实例&#xff0c;配置基地址&#xff0c;配置拦截器,目录&#xff1a;utils/http.js 基地址&#xff1a;在每次访问时&#xff0c;自动作为相对路径的根 // axios 基础封装 import axios from "axios";…

2-2-18-9 QNX系统架构之文件系统(一)

阅读前言 本文以QNX系统官方的文档英文原版资料为参考&#xff0c;翻译和逐句校对后&#xff0c;对QNX操作系统的相关概念进行了深度整理&#xff0c;旨在帮助想要了解QNX的读者及开发者可以快速阅读&#xff0c;而不必查看晦涩难懂的英文原文&#xff0c;这些文章将会作为一个…

Python基于滑动窗口CNN损伤梁桥数据、故宫城墙图像数据分类可视化|数据分享

全文链接&#xff1a;https://tecdat.cn/?p38442 分析师&#xff1a;Yufei Guo 在现代土木结构工程领域&#xff0c;结构损伤的准确识别与定位对于保障基础设施的安全性和耐久性具有极为关键的意义。传统的人工检查方法&#xff0c;如目视检查以及借助专业设备进行检测&#x…

MyBatis的if标签的基本使用

在MyBatis框架中&#xff0c;if标签用于在构建SQL语句时&#xff0c;根据参数条件判断的结果&#xff0c;动态地选择加入或不加where条件中。 一 常见使用 在使用MyBatis处理查询逻辑的时候&#xff0c;常用的是判断一些参数是否为空&#xff0c;列举常用的几种情况展示 1.1…

RabbitMQ原理架构解析:消息传递的核心机制

文章目录 一、RabbitMQ简介1.1、概述1.2、特性 二、RabbitMQ原理架构三、RabbitMQ应用场景3.1、简单模式3.2、工作模式3.3、发布订阅3.4、路由模式3.5 主题订阅模式 四、同类中间件对比五、RabbitMQ部署5.1、单机部署5.2、集群部署&#xff08;镜像模式&#xff09;5.3、K8s部署…

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测,含优化前后对比

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测&#xff0c;含优化前后对比 目录 NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测&#xff0c;含优化前后对比预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介…

【0346】Postgres内核 Startup Process 通过 signal 与 postmaster 交互实现 (5)

1. Startup Process 进程 postmaster 初始化过程中, 在进入 ServerLoop() 函数之前,会先通过调用 StartChildProcess() 函数来开启辅助进程,这些进程的目的主要用来完成数据库的 XLOG 相关处理。 如: 核实 pg_wal 和 pg_wal/archive_status 文件是否存在Postgres先前是否发…

说说Elasticsearch拼写纠错是如何实现的?

大家好&#xff0c;我是锋哥。今天分享关于【说说Elasticsearch拼写纠错是如何实现的&#xff1f;】面试题。希望对大家有帮助&#xff1b; 说说Elasticsearch拼写纠错是如何实现的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Elasticsearch 中&…

NAT拓展

NAT ALG&#xff08;NAT应用级网&#xff09; 为某些应用层协议&#xff0c;因为其报文内容可能携带IP相关信息&#xff0c;而普通NAT转化无法将这些IP转化&#xff0c;从而导致协议无法正常运行 例如FTP&#xff0c;DHCP&#xff0c;RSTP&#xff0c;ICMP&#xff0c;IPSEC…

Flutter:封装发送验证码组件,注册页使用获取验证码并传递控制器和验证码类型

验证码&#xff1a;view import package:flutter/material.dart; import package:get/get.dart; import index.dart;class SendcodePage extends GetView<SendcodeController> {// 接收注册页面&#xff0c;传进来的手机号控制器&#xff0c;和发送验证码的类型final Tex…

【目标跟踪】Anti-UAV数据集详细介绍

Anti-UAV数据集是在2021年公开的专用于无人机跟踪的数据集&#xff0c;该数据集采用RGB-T图像对的形式来克服单个类型视频的缺点&#xff0c;包含了318个视频对&#xff0c;并提出了相应的评估标准&#xff08;the state accurancy, SA)。 文章链接&#xff1a;https://arxiv.…

Linux的文件系统

这里写目录标题 一.文件系统的基本组成索引节点目录项文件数据的存储扇区三个存储区域 二.虚拟文件系统文件系统分类进程文件表读写过程 三.文件的存储连续空间存放方式缺点 非连续空间存放方式链表方式隐式链表缺点显示链接 索引数据库缺陷索引的方式优点&#xff1a;多级索引…

C++优选算法十七 多源BFS

1.单源最短路问题 一个起点一个终点。 定义&#xff1a;在给定加权图中&#xff0c;选择一个顶点作为源点&#xff0c;计算该源点到图中所有其他顶点的最短路径长度。 2.多源最短路问题 定义&#xff1a;多源最短路问题指的是在图中存在多个起点&#xff0c;需要求出从这些…

DAY141权限提升-Linux系统权限提升篇VulnhubCapability能力LD_Preload加载数据库等

一、演示案例-Linux系统提权-Web&用户-数据库类型 复现环境&#xff1a;Raven: 2 ~ VulnHub 1、信息收集 http://192.168.139.155/vendor/ 2、Web权限获取 searchsploit phpmailer find / -name 40969.py cp /usr/share/exploitdb/exploits/php/webapps/40969.py p.py p…

使用nginx请求转发时前端报跨域问题解决

当其他接口都没有问题&#xff0c;后端也进行了跨域的配置时&#xff0c;此时问题应该就出现在nginx中 我发现当上传文件大小小于1m时并不会发生错误&#xff0c;所以我们应该配置一下nginx允许上传文件的大小 在nginx.conf中添加 在nginx目录下重启nginx即可 &#xff08;Wi…

凭借 SpringBoot 构建新冠密接者跟踪系统:快速开发与部署优势凸显

第3章 系统分析 在进行系统分析之前&#xff0c;需要从网络上或者是图书馆的开发类书籍中收集大量的资料&#xff0c;因为这个环节也是帮助即将开发的程序软件制定一套最优的方案&#xff0c;一旦确定了程序软件需要具备的功能&#xff0c;就意味着接下来的工作和任务都是围绕着…