rust线程

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文档好好看一遍,消化第一手知识,而不要只看文章,看别人消化了加工出的知识。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357

推荐阅读更多精彩内容