2015-06-01 3 views
3

Рассмотрите следующий пример кода, у меня есть вектор JoinHandlers, в котором мне нужно его перебрать, чтобы присоединиться к основному потоку, однако при этом я получаю ошибку error: cannot move out of borrowed content.Невозможно переместить данные из Mutex

let threads = Arc::new(Mutex::new(Vec::new())); 

for _x in 0..100 { 
    let handle = thread::spawn(move || { 
      //do some work 
    } 

    threads.lock().unwrap().push((handle)); 
} 

for t in threads.lock().unwrap().iter() { 
    t.join(); 
} 
+2

у вас в вашем коде есть несогласованные скобки –

ответ

6

К сожалению, вы не можете делать этого напрямую. Когда Mutex потребляет структуру данных, которую вы ей подавали, вы не можете вернуть ее обратно по значению снова. Вы можете получить только ссылку &mut, которая не позволит выйти из нее. Так что даже into_iter() не будет работать - ему нужен self аргумент, который он не может получить от MutexGuard.

Однако обходное решение. Вы можете использовать Arc<Mutex<Option<Vec<_>>>> вместо Arc<Mutex<Vec<_>>>, а затем просто take() значение из мьютекса:

for t in threads.lock().unwrap().take().unwrap().into_iter() { 
} 

Тогда into_iter() будет работать нормально, как значение перемещается в вызывающем потоке.

Конечно, вам нужно будет построить вектор и нажать на него соответствующим образом:

let threads = Arc::new(Mutex::new(Some(Vec::new()))); 
... 
threads.lock().unwrap().as_mut().unwrap().push(handle); 

Однако, лучший способ это просто перенесите Arc<Mutex<..>> слой в целом (конечно, если это значение не используется из других потоков).

+0

да, отбрасывание 'Arc >' это путь. –

+0

Я попытался удалить «Arc >», и теперь у меня что-то осталось по линиям 'let mut threads = Vec :: new();' 'threads.push (handle);' и 'for t в thread.iter() {', но я все еще вижу ошибку: не могу выйти из заимствованного контента' t.join() ' –

+1

вам нужно' in_iter() 'вместо' iter() ' –

Смежные вопросы