Почему я могу "переместить" static & str в несколько потоков в Rust? - PullRequest
0 голосов
/ 12 октября 2018

Я бы хотел лучше понять семантику следующего кода Rust:

use std::thread;

fn main() {
    let immutable = "I am not mutable";
    let mut mutable = "I am mutable";

    let handle1 = thread::spawn(move || {
        println!("Thread 1 says: {}", immutable);
    });

    let handle2 = thread::spawn(move || {
        println!("Thread 2 says: {}", immutable);
    });

    let handle3 = thread::spawn(move || {
        println!("Thread 3 says: {}", mutable);
        mutable = "go away";
    });

    let handle4 = thread::spawn(move || {
        println!("Thread 4 says: {}", mutable);
    });

    handle1.join().unwrap();
    handle2.join().unwrap();
}

Я не понимаю, почему этот код компилируется.Я поделился переменной mutable между несколькими потоками и даже мутировал.Что именно происходит за кадром с памятью здесь?Делаем ли мы несколько указателей на одну и ту же строку в статической памяти?Мы помещаем две разные статические строки в память?Меня не удивляет тот факт, что у меня два потока читают из одного неизменного элемента, но наличие двух потоков, считывающих изменяемую переменную, делает это.

Обратите внимание, что даже если поток 3 запускается до 4, 4 не работаетотражает обновленную строку, которую поток 3 устанавливает в своем операторе println!.Наконец, поскольку я не передал использование &immutable, означает ли это, что значение «перемещается» в каждый поток, а не в адрес реальной памяти?

1 Ответ

0 голосов
/ 12 октября 2018

Я разделил одну и ту же переменную mutable между несколькими потоками и даже мутировал ее.

Нет, вы скопировали ссылку на одну и ту же статическую строку в несколько потоков.Ссылка указывает на постоянную статическую строку, которую нельзя изменить.Ссылки только для чтения: Copy, так что вы можете переместить их в несколько замыканий.

Что именно происходит за кадром с памятью здесь?

Срез строки - это указатель на начало строки в памяти вместе с длиной.Ваши переменные mutable и immutable содержат только эти две части информации, и только эти части могут изменяться для mutable.Фактические строки, на которые указывают переменные, являются неизменяемыми.При «перемещении» переменных в замыкания они фактически копируются, поскольку &str равно Copy.Единственная информация, которая копируется - это указатель и длина, а не фактические строковые данные.В результате вы получаете несколько указателей на одну и ту же постоянную память, которая не допускает скачки данных и соответствует правилам безопасности памяти Rust.

Кроме того, обратите внимание, что даже если поток 3 выполняется раньше4, 4 не отражает обновленную строку, которую поток 3 устанавливает в своем println!оператор.

Вы изменяете только копию указателя и длину.В потоке 3 mutable становится отдельной переменной, локальной для замыкания, и вы только изменяете это.

Наконец, поскольку я не передал использование &immutable, означает ли это, что значение«перемещается» в каждый поток, а не в реальный адрес памяти?

Переменная immutable имеет тип &'static str, поэтому она уже является ссылкой;&immutable будет ссылкой на ссылку.

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