Rust 学习笔记

rust - 多线程学习笔记

2020-02-22  本文已影响0人  国服最坑开发

0x01 最一般的用法

use std::str;
use std::thread;

fn main() {
    let mut v = vec![];
    for id in 0..5{
        let child = thread::spawn(move || {
            println!("in child: {}", id);
        });
        v.push(child);
    }

    println!("in main : join before");

    for child in v {
        child.join();
    }

    println!("in main : join after");
}

结果:

in child: 0
in child: 1
in child: 2
in main : join before
in child: 3
in child: 4
in main : join after

0x02 定制线程参数

use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};

fn main() {
    let mut v = vec![];
    for id in 0..5 {
        let thread_name = format!("child-{}", id);
        let size:usize = 3*1024;
        let builder = Builder::new().name(thread_name).stack_size(size);
        let child = builder.spawn(move ||{
            println!("in child : {}", id);
            if id == 3 {
                // panic::catch_unwind(||{
                //     panic!("oh no!");
                // });
                println!("in {} do sm", current().name().unwrap());
            }
        }).unwrap();
        v.push(child);
    }

    for child in v{
        child.join().unwrap();
    }
}

结果

in child : 1
in child : 0
in child : 3
in child-3 do sm
in child : 4
in child : 2

0x03 ThreadLocal 线程安全变量

use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};


use std::cell::RefCell;

fn main() {
    // create a thread local static var
    thread_local!(static FOO:RefCell<u32> = RefCell::new(1));
    FOO.with(|f|{
        // in main thread : check if 1, and assign to 2
        assert_eq!(*f.borrow(), 1);
        *f.borrow_mut() = 2;
    });

    let m = thread::spawn(||{
        FOO.with(|f| {
            // in sub thread: check 1, and assign to 3
            assert_eq!(*f.borrow(),1);
            *f.borrow_mut() = 3;
        });
    });

    m.join();

    FOO.with(|f|{
        // in main thread: check 2
        assert_eq!(*f.borrow(), 2);
    });
}

结论就是, 没啥输出. 主线程里更新成2后, 子线程的修改, 不影响主线程的内容.

0x04 线程阻塞&打开

park(): 阻塞线程, unpack(): 手动激活线程
thread::sleep 当前线程睡一段时间后, 自动后续执行

use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
use std::time::Duration;

fn main() {
    let parked_thread = thread::Builder::new().spawn(|| {
        println!("Parking thread");
        thread::park();
        println!("Thread unparked");
    }).unwrap();

    thread::sleep(Duration::from_millis(1000));
    println!("Unpack the thread" );
   
    parked_thread.thread().unpark();
    parked_thread.join().unwrap();

    println!("Done!");
}

结果

Parking thread
Unpack the thread
Thread unparked
Done!

0x05 线程锁 Mutex

跨线程更新数据 , 需要对线程进行上锁. Mutex::lock()

use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
use std::time::Duration;

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

fn main() {
    let mut s = Arc::new(Mutex::new("Hello".to_string()));
    let mut v = vec![];

    for _ in 0..3 {
        let mut s_clone = s.clone();
        let child = thread::spawn(move || {
            let mut s_clone = s_clone.lock().unwrap();
            s_clone.push_str(" Rust!");
        });
        v.push(child);
    }

    for c in v {
        c.join();
    }

    println!("{:?}", s);
}

输出

Mutex { data: "Hello Rust! Rust! Rust!" }

0x06 Barrier, 线程等待

use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
use std::time::Duration;

use std::sync::{Arc, Mutex, Barrier};

fn main() {
    let mut handles = Vec::with_capacity(5);
    let barrier = Arc::new(Barrier::new(5));

    for _ in 0..5 {
        let c = barrier.clone();
        handles.push(thread::spawn(move || {
            println!("before wait");
            c.wait();
            println!("after wait");
        }))
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
}

结果

before wait
before wait
before wait
before wait
before wait
after wait
after wait
after wait
after wait
after wait

0x07 Channel 通信

chanel . recv 会阻塞当前线程

use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
use std::time::Duration;

use std::sync::{Arc, Mutex, Barrier};

use std::sync::mpsc::channel;

fn main() {
    let (tx, rx) = channel();
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(1000));
        tx.send(10).unwrap();
    });

    let r = rx.recv().unwrap();
    assert_eq!(r, 10);
    println!("{}", r);
}

结果 : 10

上一篇下一篇

猜你喜欢

热点阅读