多进程与多线程

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多平台发布

相关推荐
千|寻4 分钟前
【画江湖】langchain4j - Java1.8下spring boot集成ollama调用本地大模型之问道系列(第一问)
java·spring boot·后端·langchain
程序员岳焱18 分钟前
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
后端·sql·mysql
龚思凯24 分钟前
Node.js 模块导入语法变革全解析
后端·node.js
天行健的回响27 分钟前
枚举在实际开发中的使用小Tips
后端
wuhunyu32 分钟前
基于 langchain4j 的简易 RAG
后端
techzhi32 分钟前
SeaweedFS S3 Spring Boot Starter
java·spring boot·后端
写bug写bug2 小时前
手把手教你使用JConsole
java·后端·程序员
苏三说技术2 小时前
给你1亿的Redis key,如何高效统计?
后端
JohnYan2 小时前
工作笔记- 记一次MySQL数据移植表空间错误排除
数据库·后端·mysql
程序员清风2 小时前
阿里二面:Kafka 消费者消费消息慢(10 多分钟),会对 Kafka 有什么影响?
java·后端·面试