2013-07-26 2 views
6

Возможно ли обмен измененной переменной между несколькими потоками в Rust? Учитывая следующее:Совместное использование изменяемых переменных между потоками в ржавчине

fn main() { 

    let mut msg = "Hi"; 
    // ... 
    msg = "Hello, World!"; 

    do spawn { 
     println(msg); 
    } 

    do spawn { 
     println(msg); 
    } 

} 

Я получаю эту ошибку:

error

Переменные просто должна быть только для чтения к порождены потокам. Переменная должна быть изменчивой, хотя, потому что то, что я действительно пытаюсь сделать, это поделиться HashMap между несколькими потоками. Насколько я знаю, нет возможности заполнить HashMap, если он не изменен. Даже если есть способ сделать это, я все равно заинтересован в том, как добиться чего-то подобного в целом.

Спасибо!

ответ

8

Это ограничение планируется удалить в будущей версии языка. Тем не менее, вы можете исправить эту проблему с let msg = msg; до первого do spawn. Это будет переместить значение msg в неизменное место, эффективно изменяя его изменчивость.

+0

Это сделало трюк! Спасибо! –

+1

Когда вы говорите, что «это ограничение планируется удалить», что именно меняется? Копировать-на-захват станет по умолчанию? Или вы сможете захватить изменяемую переменную, пока ваша лямбда создается после последнего присвоения ей? –

3

В случае обмена строкой «Hello, World!» Вам просто нужно переместить переменную обратно в неизменяемое место (например, «let mut msg = .....; let msg = msg ; ").

Возможно, вы также захотите не делать отдельную копию хэш-карты для каждого потока, который ее получает, но в этом случае вы также захотите поместить его внутри ARC (обертка с атомной ссылкой подсчитана) Найти в extra::arc.

+0

Итак, когда вы делаете 'let msg = msg;' Rust делает неизменяемую копию 'msg' для каждого порожденного потока? –

+0

@EvanByrne в этом случае Rust затеняет предыдущую изменчивую ссылку с новой неизменной ссылкой. Эта неизменяемая ссылка может быть передана потокам. По крайней мере, так я понимаю это поведение. –

3

Ответ «в целом» (о сохранении хеш-таблицы, изменяемой при ее совместном использовании) заключается в том, что это невозможно; Руста была специально разработана, чтобы запретить совместное использование изменчивого состояния, чтобы избежать определенных видов ошибок и защитить определенные виды безопасности (и по другим причинам).

Однако можно создать нечто похожее на общую измененную хеш-таблицу. Представьте, что одна задача имеет изменяемую хеш-таблицу. Вы можете написать код, чтобы другие задачи могли отправлять ему сообщения, говорящие «по существу,« обновить хеш-таблицу, чтобы 5 карт до 18 »или« скажи мне, что 7 карт ».

Что делает эта косвенность? Во-первых, копируя значения в сообщения, невозможно, чтобы другая задача попирала всю память, которую вы находите в середине чтения (большая проблема безопасности), а во-вторых, путем написания кода косвенно, более понятным для программиста что является и не является атомной операцией; программист будет знать, что не следует ожидать, что два последовательных сообщения о содержимом хеш-таблицы не обязательно относятся к одной и той же версии хеш-таблицы, предположение, которое совершенно верно (по крайней мере, в Rust, благодаря некоторым другим ограничениям) около двух последовательных чтений из нерасширенной, изменяемой хэш-таблицы.

+0

Это, безусловно, похоже на многообещающий подход. Есть ли что-то конкретное в стандартной библиотеке, которое помогло бы мне выполнить такую ​​вещь? –

+0

Не то, чтобы я знаю, извините!Стандартная библиотека все еще растет; вы можете захотеть добавить его самостоятельно. –

+0

Если я выясню способ сделать это, я обязательно сделаю его доступным на github :) –