rust并发

文章目录

Rust对多线程的支持

rust默认仅支持一对一线程,也就是说操作系统线程。

可以引入crate包来使用绿色线程。

std::thread::spawn创建线程

rust 复制代码
use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }

    handle.join().unwrap();
}

编译

bash 复制代码
 cargo run
warning: unused `Result` that must be used
  --> src/main.rs:17:5
   |
17 |     handle.join();
   |     ^^^^^^^^^^^^^
   |
   = note: this `Result` may be an `Err` variant, which should be handled
   = note: `#[warn(unused_must_use)]` on by default
help: use `let _ = ...` to ignore the resulting value
   |
17 |     let _ = handle.join();
   |     +++++++

warning: `smartPtr` (bin "smartPtr") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/smartPtr`
hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!

线程与 move 闭包

rust 复制代码
use std::thread;

fn main() {
    let v = vec![1, 2, 3];

    let handle = thread::spawn(move || {
        println!("Here's a vector: {:?}", v);
    });

    handle.join().unwrap();
}

编译

rust 复制代码
 cargo run
    Blocking waiting for file lock on build directory
   Compiling smartPtr v0.1.0 (/home/wangji/installer/rust/bobo/smartPtr)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 19.07s
     Running `target/debug/smartPtr`
Here's a vector: [1, 2, 3]

使用消息传递在线程间传送数据

std::sync::mpsc::channel()

只支持多个生产者和一个消费者

rust 复制代码
use std::sync::mpsc; //mpsc:multi-producer, single-consumer
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("hi");
        tx.send(val).unwrap();
    });

    // recv()会阻塞
    // try_recv()是非阻塞,适合使用loop来尝试接收
    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}

for received in rx接收

rust 复制代码
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];

        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    // 当发送方tx结束了,接收方rx就会结束(for循环也会结束)
    for received in rx {
        println!("Got: {}", received);
    }
}

两个producer

rust 复制代码
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    // --snip--

    let (tx, rx) = mpsc::channel();

    let tx1 = tx.clone(); //tx和tx1都连接到mpsc::channel()
    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];

        for val in vals {
            tx1.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    thread::spawn(move || {
        let vals = vec![
            String::from("more"),
            String::from("messages"),
            String::from("for"),
            String::from("you"),
        ];

        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    for received in rx {
        println!("Got: {}", received);
    }

    // --snip--
}

共享状态并发

std::sync::Mutex

rust 复制代码
use std::sync::Mutex;

fn main() {
    let m = Mutex::new(5);

    {
        // m.lock()会阻塞当前线程,获取锁位置
        let mut num = m.lock().unwrap();
        *num = 6;
        // 退出时会自动释放锁
    }

    println!("m = {:?}", m);
}

编译及运行

bash 复制代码
 cargo run
   Compiling smartPtr v0.1.0 (/home/wangji/installer/rust/bobo/smartPtr)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 6.57s
     Running `target/debug/smartPtr`
m = Mutex { data: 6, poisoned: false, .. }

在多个线程间共享Mutex,使用std::sync::Arc

rust 复制代码
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;

fn main() {
    // Mutex于Arc经常一起使用
    // Rc::new可以让Mutex拥有多个所有者
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter); //Rc::clone不是真正的clone,只是增加引用计数
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap(); //counter.lock()可以获得可变的引用(类似于RefCell智能指针)

            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Result: {}", *counter.lock().unwrap());
}

编译

bash 复制代码
 cargo run
   Compiling smartPtr v0.1.0 (/home/wangji/installer/rust/bobo/smartPtr)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 5.85s
     Running `target/debug/smartPtr`
Result: 10

参考

相关推荐
该用户已不存在21 小时前
Mojo vs Python vs Rust: 2025年搞AI,该学哪个?
后端·python·rust
大卫小东(Sheldon)1 天前
写了一个BBP算法的实现库,欢迎讨论
数学·rust
echoarts1 天前
Rayon Rust中的数据并行库入门教程
开发语言·其他·算法·rust
ftpeak2 天前
从零开始使用 axum-server 构建 HTTP/HTTPS 服务
网络·http·https·rust·web·web app
咸甜适中2 天前
rust语言 (1.88) 学习笔记:客户端和服务器端同在一个项目中
笔记·学习·rust
咸甜适中2 天前
rust语言 (1.88) egui (0.32.2) 学习笔记(逐行注释)(二十八)使用图片控件显示图片
笔记·学习·rust·egui
huli33202 天前
pingora_web:首款基于 Cloudflare Pingora 的企业级 Rust Web 框架
rust
Pomelo_刘金2 天前
如何优雅地抽离 Rust 子工程:以 rumqttd 为例
rust
几颗流星2 天前
Rust 常用语法速记 - 错误处理
后端·rust
向上的车轮2 天前
如何用 Rust 重写 SQLite 数据库(二):是否有市场空间?
数据库·rust·sqlite