网站首页 > 基础教程 正文
1. 基础概念对比
Go的并发模型
- goroutine:Go的轻量级线程,由Go运行时管理
- CSP模型:基于通信(Channel)来共享内存
- M:N调度:goroutine被多路复用到少量OS线程上
Rust的并发模型
- OS线程:标准库提供的一对一线程模型
- async/await:基于Future的异步编程
- 绿色线程:通过第三方库(如tokio)实现的M:N调度
2. 线程创建与管理
Go的goroutine
func main() {
// 启动goroutine只需在函数调用前加go关键字
go func() {
fmt.Println("Hello from goroutine")
}()
time.Sleep(time.Second) // 等待goroutine完成(实际应用中应用channel或WaitGroup)
}
特点:
- 创建成本极低(初始2KB栈,可动态增长)
- 由Go运行时调度,非抢占式(基于函数调用切换)
- 无法直接获取返回值
Rust的线程
use std::thread;
fn main() {
// 使用thread::spawn创建OS线程
let handle = thread::spawn(|| {
println!("Hello from thread!");
42 // 返回值
});
// 等待线程完成并获取返回值
let result = handle.join().unwrap();
println!("Thread returned: {}", result);
}
特点:
- 一对一映射到OS线程,创建成本较高
- 完全抢占式调度
- 可通过join获取返回值
- 更精细的控制(栈大小、优先级等)
3. 共享内存与同步
Go的方式
func main() {
var counter int
var wg sync.WaitGroup
var mu sync.Mutex
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
mu.Lock()
counter++
mu.Unlock()
wg.Done()
}()
}
wg.Wait()
fmt.Println(counter)
}
特点:
- 鼓励使用channel通信
- 但仍有sync包提供传统同步原语(Mutex, RWMutex, WaitGroup等)
- 数据竞争检测工具(-race标志)
Rust的方式
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..1000 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
特点:
- 所有权系统强制线程安全
- Arc(原子引用计数)用于共享所有权
- Mutex等同步原语提供内部可变性
- 编译时防止数据竞争
4. 异步编程对比
Go的协程
func fetchData(url string, ch chan<- string) {
resp, _ := http.Get(url)
body, _ := io.ReadAll(resp.Body)
ch <- string(body)
}
func main() {
ch := make(chan string)
go fetchData("https://example.com", ch)
fmt.Println(<-ch) // 阻塞等待结果
}
特点:
- 同步风格的异步代码
- channel是主要通信机制
- select实现多路复用
- 运行时内置调度器
Rust的async/await
use tokio::io::AsyncReadExt;
async fn fetch_data(url: &str) -> Result<String, Box<dyn std::error::Error>> {
let mut resp = reqwest::get(url).await?;
let body = resp.text().await?;
Ok(body)
}
#[tokio::main]
async fn main() {
let result = fetch_data("https://example.com").await;
println!("{:?}", result);
}
特点:
- 基于Future trait的显式异步
- 需要选择运行时(tokio, async-std等)
- .await挂起当前任务但不阻塞线程
- 更精细的控制但更复杂
5. 性能对比
特性 | Go | Rust |
线程启动成本 | 极低(~2KB) | 较高(1MB默认栈) |
上下文切换 | 快速(用户态调度) | 较慢(内核调度) |
内存占用 | 较高(GC开销) | 较低(无GC) |
吞吐量 | 高(适合IO密集型) | 极高(适合计算密集型) |
延迟 | 较低(协作式调度可能引入延迟) | 极低(完全抢占式) |
6. 错误处理对比
Go的并发错误处理
func worker(ch chan<- error) {
defer close(ch)
if err := doSomething(); err != nil {
ch <- err
}
}
func main() {
errCh := make(chan error)
go worker(errCh)
if err := <-errCh; err != nil {
log.Fatal(err)
}
}
Rust的并发错误处理
fn worker() -> Result<(), Box<dyn std::error::Error>> {
do_something()?;
Ok(())
}
fn main() {
let handle = thread::spawn(|| {
worker().unwrap(); // 或更复杂的错误处理
});
handle.join().unwrap();
}
7. 选择建议
选择Go当:
- 需要快速开发并发应用
- 处理大量IO密集型任务
- 想要简单的并发模型
- 需要内置的完善工具链(测试、性能分析等)
选择Rust当:
- 需要极致性能和控制力
- 处理计算密集型任务
- 需要内存安全保证
- 项目长期维护性更重要
8. 高级特性
Go的独特特性
- GMP调度模型:高效的goroutine调度
- 网络轮询器:集成的高效IO多路复用
- 垃圾回收:简化内存管理但可能引入停顿
Rust的独特特性
- 无惧并发:编译时防止数据竞争
- 零成本抽象:异步运行时是可选的库
- 无畏并发:灵活选择并发范式(消息传递/共享内存)
两种语言都提供了强大的并发编程能力,但哲学和实现方式大不相同。Go追求简单和生产力,Rust追求控制和性能。根据项目需求选择合适的工具是关键。
猜你喜欢
- 2025-06-12 实例解析C++多线程并发---异步编程
- 2025-06-12 Rust + Slint异步UI编程的奥秘,让你的应用永不假死!
- 2025-06-12 25道C++经典面试题详解,附全套学习资料免费领!
- 2025-06-12 Rust并发编程中的内部可变性(rust 并发)
- 2025-06-12 深入解析C++并发编程:从多线程到现代C++并发库
- 2025-06-12 C++ 创建新线程的核心指南:从基础到关键要点
- 2025-06-12 Rust 语言的借用规则:构筑安全内存管理体系的核心保障机制
- 2025-06-12 C++线程池的原理和方法实践(c线程池实现原理)
- 2025-06-12 你们在编程时遇到过什么离谱的bug吗?
- 2025-06-12 rust 扫描内网ip端口(rust局域网)
- 最近发表
- 标签列表
-
- jsp (69)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- pythonif (86)
- location.href (69)
- dockerexec (65)
- tail-f (79)
- queryselectorall (63)
- location.search (79)
- bootstrap教程 (74)
- deletesql (62)
- linuxgzip (68)
- 字符串连接 (73)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)