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

参考

相关推荐
疏狂难除2 小时前
随便玩玩lldb (二)
开发语言·后端·rust
Rust语言中文社区3 小时前
【Rust日报】 丰田“先锋”选择了 Rust
开发语言·后端·rust
邹小邹-AI3 小时前
Rust + 前端:下一个十年的“王炸组合”
开发语言·前端·rust
芳草萋萋鹦鹉洲哦7 小时前
【tauri+rust】App会加载白屏,有时显示在左上角显示一小块,如何优化
开发语言·后端·rust
zengyuhan5037 小时前
Windows BLE 开发指南(Rust windows-rs)
前端·rust
醉方休7 小时前
Webpack loader 的执行机制
前端·webpack·rust
1***s6328 小时前
Rust在WebAssembly中的应用实践
开发语言·rust·wasm
p***434820 小时前
Rust网络编程模型
开发语言·网络·rust
2***656321 小时前
数据库操作与数据管理——Rust 与 SQLite 的集成
数据库·rust·sqlite