Получить HashMap из потока - PullRequest
       12

Получить HashMap из потока

0 голосов
/ 25 марта 2019

Я пытаюсь получить значение из потока, в данном случае HashMap. Я сократил код до следующего (я изначально пытался поделиться HashMap Содержит Vec):

use std::thread;
use std::sync::mpsc;
use std::sync::Mutex;
use std::sync::Arc;
use std::collections::HashMap;

fn main() {
    let(tx, rx) = mpsc::channel();

    let n_handle= thread::spawn( || {
        tx.send(worker());
    });

    print!("{:?}", rx.recv().unwrap().into_inner().unwrap());
}


fn worker() -> Arc<Mutex<HashMap<String, i32>>>{
    let result: HashMap<String, i32> = HashMap::new();
    // some computation
    Arc::from(Mutex::from(result))
}

Все еще Руст говорит, что:

std::sync::mpsc::Sender<std::sync::Arc<std::sync::Mutex<std::collections::HashMap<std::string::String, i32>>>> нельзя безопасно разделить между потоками

Я прочитал некоторые запутанные вещи о размещении всего в Arc<Mutex<..>>, которые я также попробовал со значением:

let result: HashMap<String, Arc<Mutex<i32>>> = HashMap::new();

Может кто-нибудь указать мне на документ, который объясняет использование mpsc :: channel со значениями, такими как HashMaps? Я понимаю, почему это не работает, так как для HashMap не реализована функция синхронизации Sync, которая необходима для обмена данными. Тем не менее я понятия не имею, как заставить его работать.

1 Ответ

2 голосов
/ 25 марта 2019

Вы можете передавать значения между потоками, используя mpsc канал.

Пока вы не пометите свой thread::spawn ключевым словом move, например:

thread::spawn(move || {});

Так как выне пометил его ключевым словом move, тогда внешние переменные не перемещаются в область потока, а только делятся своими ссылками.Таким образом, вам нужно реализовать Sync признак, который каждая внешняя переменная, которую вы используете.

mpsc::Sender не реализует Sync, поэтому вы получаете ошибку, которая не может быть разделена между потоками.

Решение для вашего случая было бы идеальным, чтобы переместить отправителя внутрь области потока с помощью перемещения следующим образом:

use std::collections::HashMap;
use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let _ = tx.send(worker());
    });

    let arc = rx.recv().unwrap();
    let hashmap_guard = arc.lock().unwrap();
    print!(
        "HashMap that retrieved from thread : {:?}",
        hashmap_guard.get("Hello").unwrap()
    );
}

fn worker() -> Arc<Mutex<HashMap<String, i32>>> {
    let mut result: HashMap<String, i32> = HashMap::new();
    result.insert("Hello".to_string(), 2);
    // some computation
    Arc::new(Mutex::new(result))
}

Детская площадка

Для получения дополнительной информации: Iрекомендую прочитать Язык программирования Rust , в частности главу по параллелизму .В нем вы познакомитесь с Arc: особенно если вы хотите поделиться своими данными между потоками.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...