Skip to content
Published at:

所有权和类型系统是一系列解决内存安全 和 并发问题

  • 如何创建线程来同时运行多段代码。
  • 消息传递(Message passing)并发,其中通道(channel)被用来在线程间传递消息。
  • 共享状态(Shared state)并发,其中多个线程可以访问同一片数据。
  • Sync 和 Send trait,他们允许 Rust 的并发保证能被扩展到用户定义的和标准库中提供 的类型中。

对于高级语言来说,只实现可能 解决方案的子集是一个合理的策略,因为高级语言所许诺的价值来源于牺牲一些控制来换取 抽象。然而对于底层语言则期望提供在任何给定的情况下有着最高的性能且对硬件有更少的 抽象。因此,Rust 提供了多种工具,以符合实际情况和需求的方式来为问题建模。

使用 spawn 创建新线程

rust
use std::{thread, time::Duration};

fn main() {
    println!("Hello, world!");
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("sub thread : {}", i);
            thread::sleep(Duration::from_millis(100));
        }
    });

    for i in 1..5 {
        println!("main thread : {}", i);
        thread::sleep(Duration::from_millis(100));
    }
    handle.join().unwrap();
}

线程与 move 闭包

rust
use std::thread;

fn main() {
    let v = vec![1, 2, 3, 4];
    let handle = thread::spawn(move || {
        println!("v = {:?}", v);
    });

    handle.join().unwrap();
}

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

rust
use std::{sync::mpsc, thread};

fn main() {
    let (sender, receiver) = mpsc::channel();
    // sender.send(()).unwrap();
    thread::spawn(move || {
        thread::sleep(std::time::Duration::from_millis(300));
        let val = String::from("msg");
        sender.send(val).unwrap();
    });

    println!("wait for msg ");
    let msg = receiver.recv().unwrap();
    println!("msg = {:?}", msg);
}

通道与所有权转移

rust
use std::{sync::mpsc, thread, time::Duration};

fn main() {
    let (sender, receiver) = mpsc::channel();
    // sender.send(()).unwrap();
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(300));
        let val = String::from("msg");
        sender.send(val).unwrap();
        // println!("val is = {:?}", val);
    });

    println!("wait for msg ");
    let msg = receiver.recv().unwrap();
    println!("msg = {:?}", msg);
}

发送多个值并观察接收者的等待

rust
use std::{sync::mpsc, thread, time::Duration};

fn main() {
    let (tx, rx) = std::sync::mpsc::channel();
    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];

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

    for msg in rx {
        println!("msg = {:?}", msg);
    }
}

通过克隆发送者来创建多个生产者

rust
use std::{sync::mpsc, thread, time::Duration};

fn main() {
    let (tx, rx) = std::sync::mpsc::channel();
    let tx1 = mpsc::Sender::clone(&tx);
    thread::spawn(move || {
        let vals = vec![
            String::from("1 hi"),
            String::from("1 from"),
            String::from("1 the"),
            String::from("1 thread"),
        ];

        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });
    thread::spawn(move || {
        let vals = vec![
            String::from("2 more"),
            String::from("2 messages"),
            String::from("2 for"),
            String::from("2 you"),
        ];
        for val in vals {
            tx1.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    for val in rx {
        println!("got val = {:?}", val);
    }
}

共享状态并发

Send :这是确保所使用的类型意在用于并发环境的 trait 之一

原子引用计数 Arc<T> atomically reference counted

使用 Arc<T> 包装一个 Mutex<T> 能够实现在多线程之间共享所有权

rust
use std::{
    sync::{Arc, Mutex},
    thread,
};

fn main() {
    let counter = Arc::new(Mutex::new(0));

    let mut handles = vec![];

    for _ in 0..10 {
        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!("counter = {:?}", *counter.lock().unwrap());
}

Mutex<T> 提供了内部可变性

使用 SyncSend trait 的可扩展并发

通过 Send 允许在线程间转移所有权

Sync 允许多线程访问