#multithreading #rust
Вопрос:
Новичок в ржавчине. Пытаюсь передать право собственности на a Vec<Option<Box<dyn CoolTrait>>>
в потоке, но я не могу разыменовать MutexGuard:
fn main() {
let cool_vec: Vec<Option<Box<dyn CoolTrait>>> = vec![];
let vec_mx = Mutex::new(cool_vec);
let mythread = thread::spawn(move || {
let mxguard = vec_mx.lock().unwrap();
do_an_action(*mxguard);
});
}
Компилятор жалуется на эту последнюю строку с:
cannot move out of dereference of MutexGuard<'_, Vec<Option<Box<dyn CoolTrait>>>
move occurs because value has type Vec<Option<Box<dyn CoolTrait>>>, which does not implement the Copy trait
Есть ли какой-нибудь способ сделать это?
Комментарии:
1. Пытаясь передать право собственности на a
Vec<_>
в потоке , вы уже передали право собственности потоку, есть ли какая-либо другая причина для разыменованияMutexGuard
? Или вы хотите иметь что-то подобное ?2. @herpderp расскажите нам, чего вы хотите достичь, а не как вы планируете это сделать
3. В принципе, основной поток должен владеть vec, как и функция do_an_action в другом потоке. Я пытаюсь передавать его туда и обратно между потоками
4. Обратите внимание, что голый
Mutex
почти всегда бесполезен, так как у него может быть только один владелец, поэтому нет необходимости в блокировке.Mutex
имеет смысл только в том случае, если он стоит за какой-то ссылкой, напримерamp;Mutex
(что почти наверняка должно быть'static
) илиArc<Mutex>
.5. @herpderp, который не может работать,
Mutex
может только раздавать (изменяемые) ссылки. Чтобы получитьVec
значение, вам нужно будетmem::take
указать значение, переместить его в функцию… тогдаmain
оно окажется пустымVec
, что было бы не очень полезно. По определению, у вас не может быть как потока, так иmain
собственного одного и того же вектора, вам нужен общий владелец (anArc
), чтобы фактически владеть вещью и обеспечивать доступ (но не передавать право собственности).
Ответ №1:
Из комментария:
Я пытаюсь передать [вектор] туда и обратно между потоками
Чтобы отправить значение потоку, вам не нужно Mutex
, вы можете просто переместить значение в закрытие, которое будет выполняться потоком:
trait CoolTrait: Send {}
fn main() {
let cool_vec: Vec<Option<Box<dyn CoolTrait>>> = vec![];
let mythread = thread::spawn(move || {
do_an_action(amp;cool_vec);
});
// do other things...
mythread.join().unwrap();
}
Обратите внимание, что CoolTrait
Send
для передачи объектов признаков между потоками необходимо использовать в качестве супер-признака (или его dyn CoolTrait
необходимо изменить dyn CoolTrait Send
).
Чтобы отправить объект обратно в основной поток после mythread
завершения, вы можете использовать возвращаемое значение закрытия, переданное thread::spawn()
:
fn main() {
let cool_vec: Vec<Option<Box<dyn CoolTrait>>> = vec![];
let mythread = thread::spawn(move || {
do_an_action(amp;cool_vec);
cool_vec
});
// cool_vec is now owned by mythread, do other things here
// ...
let cool_vec = mythread.join().unwrap();
// mythread is done and we got cool_vec back!
// ...
}
Для обмена значениями между потоками, не дожидаясь завершения потока, можно использовать каналы.