【PHP】进程、线程、协程的关系
一、进程、线程和协程
(一)进程和线程的基本概念
一个程序至少一个进程,一个进程至少一个线程。
进程: 是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态的概念,竞争计算机系统资源的基本单位;
线程: 是进程的一个执行单元,是进程内的调度实体,比进程更小的独立运行的基本单位,线程也被称为轻量级进程。
假设你在电脑上运行一个音乐播放器软件,比如常见的音乐播放器。
这个音乐播放器是一个进程,它拥有自己的内存空间和资源。你可以在操作系统中看到这个音乐播放器的进程。这个进程负责整个音乐播放过程的管理和控制,比如用户界面的显示、接收用户输入、加载音乐文件等。
在这个进程中,可能会有多个线程来处理不同的任务。比如:UI 线程:负责显示用户界面,接收用户的操作,如播放、暂停、调节音量等。音频解码线程:负责解码音频数据,将音频数据转换成数字信号以便输出到音频设备。播放控制线程:负责控制音乐的播放进度,包括开始播放、暂停、停止等操作。后台任务线程:可能会有一些后台任务,比如加载音乐文件、更新播放列表等,这些任务可能会在后台线程中执行,以免阻塞 UI 线程。
通过多线程的方式,音乐播放器可以实现同时进行多个任务。
(二)线程的意义
每个进程都有自己的地址空间,即进程空间。在网络环境下,一个服务器通常需要接收不确定数量用户的并发请求,为每一个请求都创建一个进程显然行不通,因此操作系统中线程概念被引进。
线程的执行过程是线性的,尽管中间会产生中断或者暂停,但是进程所拥有的资源只为该线状执行过程服务,一旦发生线程切换,这些资源需要被保护起来。
进程分为单线程进程和多线程进程,单线程进程宏观来看也是线性执行过程,微观上只有单一的执行过程。多线性进程宏观上是线性的,微观上多个执行操作。
(三)进程和线程的对比
相同点: 线程和进程两者均可并发执行。
区别 | 线程 | 进程 |
---|---|---|
本质区别 | 线程是处理器任务调度和执行的基本单位 | 进程是操作系统资源分配的基本单位 |
地址空间 | 同一进程中的线程共享本进程的地址空间 | 进程之间是独立的地址空间 |
资源拥有 | 同一进程内的线程共享进程的资源如内存、I/O、CPU等,一个线程崩溃可能导致整个进程都死掉 | 进程之间的资源是独立的,一个进程崩溃后,在保护模式下不会对其他进程产生影响 |
执行过程 | 每个独立的线程都有一个程序运行的入口、顺序执行序列和程序出口,但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。(线程是基于进程的) | |
其他 | 线程是处理器调度的基本单元 | 进程不是处理器调度的基本单元 |
进程和线程的优缺点:
线程执行开销小,但是不利于资源的管理和保护;
进程执行开销大,但是能够很好的进行资源管理和保护,多进程比多线程健壮。
何时使用多进程,何时使用多线程:
对资源的管理和保护要求高,不限制开销和效率时,使用多进程。(CPU密集型任务)
要求效率高,切换频繁时,资源的保护管理要求不是很高时,使用多线程。(I/O密集型任务)
(四)协程
协程: 是一种轻量级的线程,因此又称微线程。它不是由操作系统内核调度,而是由程序员自己控制调度的执行流程。
(协程是用户视角的一种抽象,操作系统并没有协程的概念。协程运行在线程之上,协程的主要思想是在用户态实现调度算法,用少量线程完成大量任务的调度。)
协程的特点:
协程类似于子程序,但执行过程中,协程内部可中断,然后转而执行其他的协程,在适当的时候再返回来接着执行,从而实现一种灵活的并发编程方式。协程之间的切换不需要涉及任何系统调用或任何阻塞调用。
协程中不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
协程运行在线程之上,更加轻量级,协程并没有增加线程总数,只是在线程的基础之上通过分时复用的方式运行多个协程,大大提高工程效率。
协程适用于有大量I/O操作业务的场景,可以到达很好的效果,一是降低了系统内存,二是减少了系统切换开销,因此系统的性能也会提升。在协程中尽量不要调用阻塞I/O的方法,比如打印,读取文件等,除非改为异步调用的方式,并且协程只有在I/O密集型的任务中才会发挥作用。
假设存在一个任务是在电脑上同时下载多个文件,并在下载完成后将它们合并成一个文件。我们可以用进程、线程和协程来实现这个任务。
使用多个进程来同时下载多个文件,每个进程都有自己的内存空间和资源。 比方说创建一个进程来下载第一个文件,另一个进程来下载第二个文件,以此类推。下载完成后,每个进程将下载的文件传递给主进程,主进程负责将它们合并成一个文件。
使用多个线程在同一个进程中并发下载多个文件。 线程共享同一个进程的资源。比如在一个程序中创建多个线程来同时下载多个文件,每个线程负责下载一个文件。线程之间可以共享内存,因此可以在下载完成后直接合并文件,不需要传递数据给主线程。
使用协程来异步下载多个文件。 在 Python 中,可以使用 asyncio 来创建协程。先定义一个异步函数来下载文件,然后在一个事件循环中同时运行多个异步函数。在下载完成后,利用异步的方式将文件合并成一个文件,不需要阻塞其他协程的执行。
二、并行和并发
并行和并发是计算机科学中常用的两个概念,它们描述了程序执行的不同方式。
(一)并行(Parallelism)
并行指的是在同一时刻执行多个任务或指令,通常是在多个处理单元(如多个 CPU 核心或多个 GPU 核心)上同时执行。
每个任务都是独立执行的,彼此之间不会受到影响,且执行顺序不受限制。
并行的目标是通过同时处理多个任务来提高整体的计算速度。
(二)并发(Concurrency)
并发指的是在相同时间段内执行多个任务,这些任务可能会交替执行,但并不一定是同时执行的。
多个任务之间可能会共享资源,因此需要考虑资源竞争和同步问题。
并发的目标是更高效地利用计算机资源,提高系统的吞吐量和响应性。
(三)单个cpu一次只能运行一个进程吗
单个 CPU 一次只能执行一个进程的指令,但是通过操作系统的进程调度机制,可以实现多个进程在 CPU 上轮流执行,使得它们在表面上看起来是同时运行的。操作系统会根据一定的调度算法,将 CPU 的时间分配给不同的进程,从而实现多任务处理。
简而言之,并行是指同时执行多个任务,而并发是指在同一时间段内处理多个任务。并行通常需要硬件支持(如多核处理器),而并发则可以在单核处理器上通过多线程或时间片轮转等技术实现。
猜你喜欢
- 【PHP】php 二维数组删除
- 在PHP中,删除二维数组通常需要通过使用循环和条件语句来实现。在实际编程中,我们通常会遇到以下两种情况需要删除二维数组:删除指定元素:需要找到要删除的元素所在的子数组,并从该子数组中删除指定元素。删除整个子数组:需要找到包含要删除的子数组的父数组,并将该子数组删除。下面我们将分别介绍这两类任务的具体实现方法。方法一:删除指定元素要删除一个指定的元素,我们需要通过循环遍历所有子数组,找到包含目标元素的子数组,并将其从该子数组中删除。以下是实现该过程的代码示例:// 定义一个二维
- 【PHP】PHP实现图片验证码的生成和验证
- PHP实现图片验证码的生成和验证在网站开发中,为了防止机器恶意攻击或者自动注册,我们经常会使用图片验证码来进行验证。本文将介绍如何使用PHP来生成和验证图片验证码,并给出具体的代码示例。生成图片验证码生成图片验证码的关键是生成随机的验证码字符串,并将其绘制到图片上。以下是一个生成图片验证码的示例代码:<?php session_start(); // 声明图片尺寸 $image_width = 100; $image_height&nb
- 【PHP】PHP依赖注入
- PHP依赖注入(Dependency Injection,DI)是一种软件设计模式,可以减少代码耦合,使得类鱼类之间的依赖关系更加清晰。以下是一个简单的PHP依赖注入的例子:<?php interface StorageInterface { public function store($data); } class DatabaseStorage im
- 【PHP】ThinkPHP如何防止SQL注入攻击
- 在ThinkPHP中,参数绑定是一种安全的方式,用于处理用户输入,特别是在构建数据库查询时。参数绑定可以防止SQL注入攻击,因为绑定的参数会被自动转义,而不是直接插入到SQL语句中。以下是在ThinkPHP中使用参数绑定的一些建议。1. 控制器中的参数绑定:在控制器中,可以使用bind方法进行参数绑定。以下是一个简单的示例:public function index($id) { $result = Db::
- 【PHP】php 判断是否是数组
- 在PHP中,判断一个变量是否是数组可以使用多种方式。以下将介绍四种判断方法:1. is_array()函数is_array()函数是PHP中判断变量是否是数组的最常用方法。该函数接受一个变量作为参数,如果参数是一个数组,则返回true;反之,返回false。下面是一个使用is_array()函数的例子:$arr = array("apple","banana","cherry"); if(is_array(
- 【PHP】php如何去掉数组内重复元素
- php去掉数组内重复元素的方法:1、使用“array_unique()”函数,去除数组中的重复数据;2、通过foreach循环遍历,通过定义一个新的数组存储不重复的数据的方法实现去重;3、使用array_flip()和array_keys()函数,可得到去重后的数组;4、使用array_filter()函数,通过使用该函数结合匿名函数的方式对原始数组进行去重。本教程操作系统:Windows10系统、PHP8.1.3版、Dell G3电脑php去除数组内重复元素的方法方法一:使用arra
- 【PHP】php解析大量数据json文件方式
- 1. 在处理超大文件时,我们可以使用逐行读取的方式来解析JSON数据。具体步骤如下:打开文件并逐行读取数据。每次读取一行数据后,使用json_decode()函数将其解析为JSON对象。对解析后的JSON对象进行处理,例如提取需要的数据或进行其他操作。继续读取下一行,重复步骤2和步骤3,直到文件读取完毕。下面是一个示例代码,演示了如何使用以上步骤来解析超大JSON文件:$file = fopen('large_file.json', 'r&#
- 【PHP】ThinkPHP与Laravel一样吗
- thinkphp和laravel是不一样的。thinkphp和laravel虽然都是php开发框架,但是有很多区别:1、渲染末班的方式不同,thinkphp用“$this->display()”的方式渲染模版,laravel使用“return view()”方法;2、laravel是一个重路由的框架,而thinkphp要有控制器方法才能正常访问。thinkphp和laravel不一样ThinkPHP是免费开源的,快速的,简单的,面向对象的轻量级PHP开发框架,ThinkPHP可以支持win
- 【Vue】前端框架 Vue3框架 使用总结(一) Vue框架的基础使用
- 【Python】ChatGPT和Python的完美结合:打造多领域聊天机器人
- 【C#】C#的DateTimePicker控件(日期控件)
- 【Go】Go语言常用命令详解(二)
- 【UniApp】如何在uniapp中实现图片上传和预览
- 【Python】深入研究matplotlib的色彩映射表
- 【Vue】Vue 单文件组件 (SFC) 规范
- 【行业动态】TIOBE4月榜单发布:C/C++深受内存安全影响、PHP辉煌不再!
- 【Python】深度掌握Python多线程编程技巧
- 【前端】JavaScript判断数组对象是否含有某个值的方法(6种)