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

参考

相关推荐
坚果派·白晓明5 小时前
【鸿蒙PC三方库移植适配框架解读系列】第八篇:扩展lycium框架使其满足rust三方库适配
c语言·开发语言·华为·rust·harmonyos·鸿蒙
码力斜杠哥13 小时前
Rust初习录(6)Rust的 if 玩法
开发语言·python·rust
Rust研习社14 小时前
Rust 的 move 语义,一次讲透
后端·rust·编程语言
WMYeah18 小时前
【无标题】
前端·rust·抽奖程序·跨平台抽奖程序
楼兰公子1 天前
buildroot 在编译rust时裁剪平台类型数量的方法
开发语言·后端·rust
Rust研习社2 天前
开源项目里的 deny.toml 是什么?
后端·rust·编程语言
铭毅天下2 天前
当搜索引擎遇上 Rust——深度解读下一代实时搜索引擎 INFINI Pizza
开发语言·后端·搜索引擎·rust
咸甜适中2 天前
rust语言学习笔记Trait之Default(默认值)
笔记·学习·rust
容智信息2 天前
AI Agent(智能体)的输出格式应该从 Markdown 转向 HTML吗?
前端·人工智能·rust·编辑器·html·prompt