美文网首页
rust线程

rust线程

作者: Wu杰语 | 来源:发表于2024-05-26 22:45 被阅读0次

    rust多线程,和erlang非常类似,都使用spawn创建一个线程。例如一个erlang的例子

    -module(thread_example).
    -export([start/0]).
    
    % 定义要在新线程中执行的函数
    print_message() ->
        io:format("Hello from the new thread~n").
    
    % 启动函数
    start() ->
        % 使用spawn函数创建一个新的线程,并传递print_message函数
        spawn(fun print_message/0),
        ok.
    

    对比一下rust,可以发现erlang和rust及其相似,rust学习了erlang。

    1. rust创建线程

    rust使用thread包负责创建线程,spawn定义如下:

    pub fn spawn<F, T>(f: F) -> JoinHandle<T> where    F: FnOnce() -> T,    F: Send + 'static,    T: Send + 'static,
    

    一个例子代码:

       let mut handles = vec![];
        
        for i in 0..NTHREADS {
            handles.push(thread::spawn(move || { println!("this is thread number {}", i);}));
        }
        
        println!("waiting for every thread");
        
        for handle in handles {
            handle.join();
        }
    

    例如说这个例子,创建10个线程,每个线程打印一个数字。

    • 注意spawn使用了闭包,打印了一个外部变量,而spawn的定义F:FnOnce(),所以在闭包前使用了move,将i的所有权转给闭包。
    • spawn返回JoinHandler,有三个方法
      • pub fn is_finished(&self) -> bool,判断该线程是否运行完毕
      • pub fn join(self) -> Result<T, Err>,调用该方法的线程会等到handle持有线程运行完毕
      • pub fn thread(&self) -> &Thread,返回handler对应的thread

    1.1 thread::Tread获取线程的id和名字

    use std::thread;
    
    
    // This is the `main` thread
    fn main() {
        println!("{:?}", thread::current().id());
        println!("{:?}", thread::current().name());
    }
    
    返回:
    ThreadId(1)
    Some("main")
    
    let handler = thread::spawn(move || {println!("hello")});
    prantln!("{:?}", handler.thread().id());
    prantln!("{:?}", handler.thread().name());
    
    返回:
    ThreadId(2)
    None
    

    1.2 thread::Builder(如何给thread命名)

    let builder = thread::Builder::new()
        .name("foo".into());
    
    let handler = builder.spawn(|| {
        println!("{:?}", thread::current().name());
    }).unwrap();
    
    handler.join().unwrap();
    

    1.3 线程中如何传递共享参数

        let v = Arc::new(Mutex::new(vec![1,2,3]));
        
        let mut handlers = vec![];
        
        for i in 0..3 {
            let clone_v = v.clone();
            handlers.push(thread::spawn(move || {clone_v.lock().unwrap().push(i)}));    
        }
        
        for handler in handlers {
            let _ = handler.join();
        }
        
        println!("{:?}", v.lock().unwrap());
    

    共享参数使用Arc只能指针来传递,Arc是个引用,其指向的值并未被复制。在操作的时候使用Mutex来完成同步。

    1.4 thread::park和thread:unpark

    use std::thread;
    use std::sync::{Arc, atomic::{Ordering, AtomicBool}};
    use std::time::Duration;
    
    let flag = Arc::new(AtomicBool::new(false));
    let flag2 = Arc::clone(&flag);
    
    let parked_thread = thread::spawn(move || {
        // We want to wait until the flag is set. We *could* just spin, but using
        // park/unpark is more efficient.
        while !flag2.load(Ordering::Acquire) {
            println!("Parking thread");
            thread::park();
            // We *could* get here spuriously, i.e., way before the 10ms below are over!
            // But that is no problem, we are in a loop until the flag is set anyway.
            println!("Thread unparked");
        }
        println!("Flag received");
    });
    
    // Let some time pass for the thread to be spawned.
    thread::sleep(Duration::from_millis(10));
    
    // Set the flag, and let the thread wake up.
    // There is no race condition here, if `unpark`
    // happens first, `park` will return immediately.
    // Hence there is no risk of a deadlock.
    flag.store(true, Ordering::Release);
    println!("Unpark the thread");
    parked_thread.thread().unpark();
    
    parked_thread.join().unwrap();
    

    注意这里调用thread::park()阻塞的是当前线程,而接触阻塞调用的是handler.thread().unpark()。
    另外还有thread::park_timeout()方法,对阻塞设置超时。

    小结

    thread包封装了比较简洁的方法,提供线程相关的操作,thread包提供了join和park方法完成线程之间的协作;构造了JoinHandler、Builder、Thread、ThreadId等结构,有序的组合除了thread操作。学习thread包,应把doc文档好好看一遍,消化第一手知识,而不要只看文章,看别人消化了加工出的知识。

    相关文章

      网友评论

          本文标题:rust线程

          本文链接:https://www.haomeiwen.com/subject/wmxcqjtx.html