rust生命周期理解(二)

#[derive(Debug)]
struct fork{}
static PHILOSOPHERS: &[&str] =
    &["Socrates", "Hypatia", "Plato", "Aristotle", "Pythagoras"];
fn main() {
    let mut hanlders = Vec::new();
    hanlders.push(fork{});
    // Make each of them think and eat 100 times
    for v in hanlders{
        (move||{
           println!("Length: {:?}",v);
       })();}
hanlders.push(fork{});

类似情况

#[derive(Debug)]
struct Fork;

fn main() {
    let mut handlers = Vec::new();
    handlers.push(Fork{});

    // Make each of them think and eat 100 times
    for v in handlers.iter() {
        let handle = thread::spawn(move || {
            for i in 0..10 {
                println!("Length: {:?}", v);
            };
        });
    }
}

会报错的原因是,for v in hanlders内部的move的确已经将所有权进行转移。for循环获取的是真实的变量。

  • 所有权的转移:在这个例子中,for v in handlers 使用了值的迭代,而不是引用。循环中的 v 直接获取了 handlers 中的每一个 Fork 实例的所有权。每次迭代,v 是一个 Fork 类型的值。

  • 安全的线程捕获:当 thread::spawn 捕获变量 v 时,捕获的是 Fork 类型的值(所有权),而不是引用。这意味着 v 不再依赖 handlers 的生命周期,因此不存在生命周期的问题。Rust 的所有权系统确保了 v 在线程的生命周期内是有效的,因此编译可以成功。

因此这里hanlders.push(fork{});又试图获取一个已经转移了的hanlers的所有权,所以报错。

另一个例子:

#[derive(Debug)]
struct fork{}
    let mut hanlders = Vec::new();
    hanlders.push(fork{});
    // Make each of them think and eat 100 times
    for v in hanlders.iter(){
        let handle = thread::spawn(move|| {
            for i in 0..10{
                println!("Length: {:?}",v);
            };
        });
    }

改成hanlders.iter(),就报错了。原因是:

  • 引用的生命周期问题handlers.iter() 返回一个迭代器,该迭代器生成对 handlers 中元素的引用。在 for v in handlers.iter() 这个循环中,v 是对 Fork 的一个引用 (&Fork)。

  • thread::spawn'static 生命周期:当你在 thread::spawn 中使用 move 关键字时,闭包会捕获其环境中的变量。在这个例子中,v 被捕获为一个引用。但是,thread::spawn 创建的线程可能会在主线程结束之后继续运行,这意味着这些捕获的引用必须具有 'static 生命周期,即它们需要在程序的整个生命周期内有效。然而,v 只是 handlers 向量的一个短期引用,不符合 'static 的要求。因此,编译器拒绝了这种用法。

改正这个问题有三个方案:

1. 想办法将局部变量的生命周期设置为static。

fn main() {
    let hanlders: &'static mut Vec<fork> = Box::leak(Box::new(Vec::new()));
   hanlders.push(fork {});
    // Make each of them think and eat 100 times
    for v in hanlders.iter() {
        thread::spawn(move || {
            println!("Length: {:?}", v);
        });

2. 将生命周期完全给到子线程

#[derive(Debug)]
struct fork{}
    let mut hanlders = Vec::new();
    hanlders.push(fork{});
    // Make each of them think and eat 100 times
    for v in hanlders{
        let handle = thread::spawn(move|| {
            for i in 0..10{
                println!("Length: {:?}",v);
            };
        });
    }

3. 可以使用Mutex做局部变量,类似这样

static HANDLERS: Mutex<Vec<String>> = Mutex::new(Vec::new());

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值