硬件发展
早期只有一个 CPU 核心:
操作系统多线程 + CPU 核心
CPU 多核
操作系统提供了创建线程的 API
直接调用该 API 来创建线程,因此最终程序内的线程数和该程序占用的操作系统线程数相等,一般称之为1:1 线程模型
Rust 只在标准库中提供了 1:1 的线程模型
用户态协程:内部实现了自己的线程模型(绿色线程、协程),程序内部的 M 个线程最后会以某种映射方式使用 N 个操作系统线程去运行,
因此称之为M:N 线程模型 Go语言
选择 Rust 由三方库提供了实现 M:N 模型
多线程、多协程、Actor 等并发编程方式
并发编程
并发与并行
并发是轮流处理,而并行是同时处理:
并发与串行:
自己队友不能在背后抢占,但是其它队的可以
传统:
传统并发设计方法通常使用共享内存和加锁机制来确保线程安全
并发的关键在于:快速轮换处理不同的任务,给用户带来所有任务同时在运行的假象
多核心并发 :但实际上,同一时刻只有 N 个任务能被同时并行的处理
Future模型 是将异步请求和代理模式结合的产物
Fork/Join模型
Actor模型
Producer-Consumer 生产者消费者模型
Master-Worker模型
CSP(Communicating Sequential Processes) channel
并发编程模型
OS 线程--多线程
事件驱动(Event driven),事件驱动常常跟回调( Callback )非线性的控制流和结果处理导致了数据流向和错误传播变得难以掌控
Coroutines)协程( 可能是目前最火的并发模型Go
actor 模型是 erlang 的杀手锏之一 无共享状态
async/await, 该模型性能高,还能支持底层编程
Future 在 Rust 中是惰性的,只有在被轮询(poll)
异步函数是异步编程的核心,而 Future 恰恰是异步函数的返回值和被执行的关键
Future模式是多线程开发中常见的设计模式,它的核心思想是异步调用。
对于Future模式来说,它无法立即返回你需要的数据,但是它会返回一个契约,将来你可以凭借这个契约去获取你需要的信息
Actor模型的核心概念包括状态(State)、行为(Behavior)和邮箱(MailBox),每个Actor通过消息传递与其他Actor进行通信。
Actor模型中的状态由Actor自己管理,
行为则是Actor接收消息后执行的操作,
邮箱则用于存储和传递消息
Cangjie
仓颉编程语言提供抢占式的并发模型,其中仓颉线程是基本的执行单元
线程由仓颉运行时自行管理并非是底层 native 线程(如操作系统线程)仓颉语言选择有栈协程作为其并发模型
通过 spawn 关键字、
一个可缺省的 ThreadContext 类型入参
和一个不包含形参的 lambda 可以创建并启动一个线程,
同时该表达式返回一个 Future<T> 的实例
并发哈希表(常作为数据缓存)和并发队列(常作为线程间传递消息的通道,处理“生产者-消费者”问题)
类
线程类 Thread 主要用于获取线程的相关信息,例如线程标识等
ThreadContext 接口类型
原子操作确保指令被原子地执行,即执行过程中不会被中断
通过 synchronized 关键字和一个 ReentrantMutex 对象
Monitor 是一个内置的数据结构,它绑定了互斥锁和单个与之相关的条件变量 notify() notifyAll() wait
MultiConditionMonitor 是一个内置的数据结构
内存模型主要解决并发编程中内存可见性的问题
数据竞争 Data Race
Cangjie runtime 仓颉线程的运行时包含了执行线程、监视器、处理器、与调度器等
共享内存作为线程间通信的基础 提供了多样化的线程间同步机制,包括原子类型变量、互斥锁、信号量等
Spin 模式 Parking 模式 Adaptive 模式
仓颉语言要求:线程的终止必须由程序员显式检查和处理。在这一设计下,线程终止是协作式的
C++
线程是通过构造std::thread对象启动
Python
threading 库可以在单独的线程中执行任何的在 Python 中可以调用的对象。
可以创建一个 Thread 对象并将你要执行的对象以 target 参数的形式提供给该对象
start() join()
threading 库中的 Lock 对象
全局解释锁(GIL)的原因,Python 的线程被限制到同一时刻只允许一个线程执行这样一个执行模型
multiprocessing 模块来创建一个进程池
queue 库中的队列
Queue 对象已经包含了必要的锁,所以你可以通过它在多个线程间多安全地共享数据
concurrent.futures 函数库有一个 ThreadPoolExecutor 类可以被用来完成这个任
ProcessPoolExecutor 类, 可被用来在一个单独的Python解释器中执行计算密集型函数
Actor模型
Actor之间的通信是单向和异步的
仅仅只有一个核心操作 send()
使用生成器(协程)替代系统线程来实现并发
编写守护进程
rust
rust 并发编程
Web 服务器、数据库驱动、消息服务等需要高并发的服务
多线程编程和 async 编程:
thread::spawn 可以创建线程
标准库中的互斥锁、(Mutex)、原子引用计数(Arc)等允许线程间共享内存的同步机制调
Rust 也提供 async/await 关键字的支持,允许开发者实现用户态协程
Go 语言提供 goroutine 实现了有栈的用户态协程 通过使用 channel 引入了 select 语句
Go 同时也支持共享内存的通信方式
Swift 提供了任务(Task)表示一个独立的并发执行单元,它是用户态协程的无栈实现,其核心是 Swift 5.5 中引入的 async/await 语
Swift 不直接支持共享内存或是消息通信方式,而是通过 Actor 模型达成并发安全
无栈协程要求在语言中引入新语法(如 async/await 关键字)
分布式编程
并发编程和网络编程
分布式系统是指将一个系统划分为多个独立部分,它们通过网络通信协作完成一个或多个共同的任务。
在分布式系统中,网络编程是实现节点通信和协作的关键
通过远程过程调用、消息队列和负载均衡等技术,网络编程实现高效节点通信和任务协调。套接字编程、多线程编程和异步编程等提供了实现手段
(不仅负责调用远程服务,还要管理远程服务)与插件化方向发
本地过程调用(LPC)--共享内存
IPC(Inter - Process Communication),即设备内的进程间通信
远程过程调用(RPC): 要调用的函数不在本地-RPC(Remote Procedure Call),
也就是设备间的进程间通信
--Call ID --如何确定方法
--序列化和反序列化 -- 如何表示数据
--网络传输--如何传输数据
通过网络来表达调用的语义和传达调用的数据
2. 消息队列
套接字编程 多线程编程 异步编程
3.REST 的基本思想是面向资源来抽象问题
标签:模型,编程,Actor,Cangjie,并发,仓颉,线程,多线程
From: https://www.cnblogs.com/ytwang/p/18560158