Why doesn't a local variable live long enough for thread::scoped?

假装没事ソ 提交于 2019-12-24 03:43:11

问题


Why doesn't Example 1 compile given that Example 2 compiles just fine? The only difference between the examples is that in Example 1 value is a function local variable, and in Example 2 value is an argument to the function.

Example 1

#![feature(scoped)]

use std::thread;
use std::sync::atomic::{AtomicUsize, Ordering};

pub fn foo<F>() {
    let mut join_guards = Vec::new();
    let value = AtomicUsize::new(0);

    for _ in 0..10 {
        join_guards.push(thread::scoped(|| {
            value.fetch_add(1, Ordering::SeqCst);
        }));
    }
}

Example 2

#![feature(scoped)]

use std::thread;
use std::sync::atomic::{AtomicUsize, Ordering};

pub fn foo<F>(value: AtomicUsize) {
    let mut join_guards = Vec::new();

    for _ in 0..10 {
        join_guards.push(thread::scoped(|| {
            value.fetch_add(1, Ordering::SeqCst);
        }));
    }
}

These are the error messages I get trying to compile Example 1:

error: `value` does not live long enough
         join_guards.push(thread::scoped(|| {
             value.fetch_add(1, Ordering::SeqCst);
         }));
note: reference must be valid for the block at 6:20...
pub fn foo<F>() {
    let mut join_guards = Vec::new();
    let value = AtomicUsize::new(0);

     for _ in 0..10 {
         join_guards.push(thread::scoped(|| {

note: ...but borrowed value is only valid for the block suffix following statement 1 at 8:40
    let value = AtomicUsize::new(0);

     for _ in 0..10 {
         join_guards.push(thread::scoped(|| {
             value.fetch_add(1, Ordering::SeqCst);
         }));

回答1:


join_guards is a vector of scoped threads with a certain shared lifetime. That lifetime is determined by which variables it closes over: value is the only one. Therefore, the lifetime of the scoped threads is the scope of value. Where is value legal? After it is defined and until it goes out of scope—that is, “the block suffix following statement 1 at 8:40”. join_guards must have as its lifetime a lifetime no greater than this, but if join_guards is defined before value, this is not the case.

The solution is to reverse the order of declaration:

let value = AtomicUsize::new(0);
let mut join_guards = Vec::new();

This explains why the second example works, also.



来源:https://stackoverflow.com/questions/29983088/why-doesnt-a-local-variable-live-long-enough-for-threadscoped

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!