多进程与多线程

Golang

Golang的GPM调度模型,多个G即goroutine,是建立在线程之上还是进程之上?

据资料,P为逻辑处理器,M为机器cpu核心数(不是物理核心数,如果有超频,则是超频后的cpu数量),两者数量一致。

用代码验证:

复制代码
package main

import (
 "fmt"
 "sync"
)

func main() {
 var wg sync.WaitGroup
 wg.Add(1)
 go func() {
  defer wg.Done()
  for {
   fmt.Println("A:", 1)
  }
 }()

 wg.Wait()
}

运行上述代码go run t.go,而后查看活动监视器

使用runtime.GOMAXPROCS(num)来设置允许该程序使用的cpu数量,最早版本默认为1,后来改为机器的(逻辑)cpu数。所以不设置,就等同于runtime.GOMAXPROCS(runtime.NumCPU())

查看进程的线程列表:

参考: mac 进程和线程工具[1]

故而,GPM中的M实际指线程。通过抽象,在用户级别实现了m个goroutine和n个线程之间的对应(一般m远远大于n)

更多关于golang的调度,可参考:

6.5 调度器[2]

Go goroutine理解[3]


nginx

典型的多进程处理模型

启动ngnix后,查看 活动监视器 如下:

此处的2个用户为nobody的工作进程,在nginx.conf中设置:


php

同nginx一样,php-fpm也是多进程模式:

可以查看并修改PHP-CGI进程的数量


redis服务端

面试常问,redis(服务端) 的所谓单线程,指的仅仅是网络请求模块使用了一个线程,即一个线程处理所有网络请求,其他模块仍用了多个线程。且最新版本中,网络请求模也支持多线程

参考: 为什么 Redis 选择单线程模型[4]

redis网络IO模型[5]


mysql服务端和postgresql服务端

两大数据库显著差异之一,就是mysql通过多线程方式,实现高并发;而pg和nginx类似,使用多进程方式。

如下:

所以mysql有线程池的说法。

而对于pg:


进程有独立的地址空间,线程则没有独立地址空间. 同一个进程的不同线程, 它们之间共享地址空间的.

对于多进程模型, 因为之间相互独立, 其优点就是安全性比较好. 一个进程的crash, 不会导致整个软件的崩溃;而线程则不行,一个进程里的某个线程crash,会影响整个进程.

多进程的缺点, 是其创建和上下文切换的开销比较大, 另外进程之间要想相互通讯需要[专门的机制(IPC)](https://dashen.tech/2020/06/16/Linux进程间通信-IPC-的几种方式/ "专门的机制(IPC "专门的机制(IPC)")")才能实现进程间通讯.

这恰恰是线程的优点, 如果是同一个进程的不同线程, 它们在一个进程的地址空间里,所以, 其相互通讯比较方便, 它们之间的切换也比较简单. (创建线程比较简单, 切换也比较轻巧, 通讯也比较方便, 相互协作比较好).

但多线程也有缺点,就是不稳定.因为同一个进程里的若干个线程,如果有一个(线程)崩溃, 就会使得整个进程的其他线程也一起崩溃, 相互干扰比较大. (相互通讯比较容易,相互干扰也比较大)

那软件设计时,一般采用多进程模型 还是多线程模型呢? 要看具体的应用场景, 比如对于浏览器软件, (浏览器的每一个选项卡, 或说每一个浏览器页面, 是用多线程还是多进程实现更好呢?) 显然是多进程,为什么呢, 因为浏览器页面之间几乎没什么通讯需求, 所以这时候线程易于通讯的优点就发挥不出来, 反而是一个线程崩溃,导致同进程其他线程崩溃这个缺点非常致命. (肯定不希望一个页面崩溃,会连带导致其他页面也崩溃) . 所以我们一般是用多进程来实现浏览器的 ,实际上是访问同一个网站的若干页面是在一个进程的不同线程(如打开了三个新浪的新闻页,这三个页面对应一个进程), 但访问不同的网站是不同的进程(如打开了两个新浪,三个搜狐,一个网易,对应三个进程)


因为早期Linux对线程支持不好,导致很多软件的Linux版本大多是多进程模型,如Oracle和Postgre.而Windows早期对线程相对就支持较好,故而某些软件的Win版本,大多采用多线程模型. 现在Linux提供了多线程支持,一般来说多线程模型更多一些.

参考资料

1

mac 进程和线程工具: https://www.cnblogs.com/brookin/p/9803173.html

2

6.5 调度器: https://draveness.me/golang/docs/part3-runtime/ch06-concurrency/golang-goroutine/

3

Go goroutine理解: https://segmentfault.com/a/1190000018150987

4

为什么 Redis 选择单线程模型: https://draveness.me/whys-the-design-redis-single-thread/

5

redis网络IO模型: https://www.cnblogs.com/hainingwyx/p/13860764.html

本文由mdnice多平台发布

相关推荐
MadPrinter8 分钟前
SpringBoot学习日记 Day11:博客系统核心功能深度开发
java·spring boot·后端·学习·spring·mybatis
dasseinzumtode9 分钟前
nestJS 使用ExcelJS 实现数据的excel导出功能
前端·后端·node.js
淦出一番成就11 分钟前
Java反序列化接收多种格式日期-JsonDeserialize
java·后端
Java中文社群14 分钟前
Hutool被卖半年多了,现状是逆袭还是沉寂?
java·后端
程序员蜗牛1 小时前
9个Spring Boot参数验证高阶技巧,第8,9个代码量直接减半!
后端
yeyong1 小时前
咨询kimi关于设计日志告警功能,还是有启发的
后端
库森学长1 小时前
2025年,你不能错过Spring AI,那个汲取了LangChain灵感的家伙!
后端·openai·ai编程
Java水解1 小时前
Spring Boot 启动流程详解
spring boot·后端
学历真的很重要1 小时前
Claude Code Windows 原生版安装指南
人工智能·windows·后端·语言模型·面试·go
转转技术团队1 小时前
让AI成为你的编程助手:如何高效使用Cursor
后端·cursor