美文网首页
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 并发

    1、启动子线程 2、线程异常 3、同步等待子线程执行完毕 4、子线程访问外部数据 5、共享可变数据 1. rust...

  • Rust入坑指南:齐头并进(下)

    前文中我们聊了Rust如何管理线程以及如何利用Rust中的锁进行编程。今天我们继续学习并发编程, 原子类型 许多编...

  • Rust:线程间共享数据

    Rust通过独特的编译期检查,在很大程序上阻止了难懂的并发bug。 本文探索Rust线程间共享数据的方式。 我们用...

  • Rust的初体验1

    1. 什么是Rust? Rust 是一种系统编程语言。 它具有惊人的运行速度,能够防止程序错误,并保证了线程安全。...

  • Rust for cpp devs - 线程

    由于 Rust 特有的 ownership 和类型检查机制,许多并发问题都可以在编译期发现,这极大地降低了风险以及...

  • Rust 共享并发状态

    线程通讯方式 线程之间的通讯方式最常见的就是通过共享内存的方式,再通过加锁保护数据在多个线程中的一致性。Rust语...

  • 用Rust实现一个多线程的web server

    在本文之前,我们用Rust实现一个单线程的web server的例子,但是单线程的web server不够高效,所...

  • 多线程 | Rust学习笔记

    作者:谢敬伟,江湖人称“刀哥”,20年IT老兵,数据通信网络专家,电信网络架构师,目前任Netwarps开发总监。...

  • rust - 多线程学习笔记

    0x01 最一般的用法 结果: 0x02 定制线程参数 结果 0x03 ThreadLocal 线程安全变量 结论...

  • Rust for cpp dev - 线程池

    在 web server[https://www.jianshu.com/p/35d9fd027dfd] 项目中,...

网友评论

      本文标题:rust线程

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