Отличный и глубокий вопрос! На него часто дают неполный ответ ("перемещается замыкание"), но давайте разберем **конкретно по байтам**, что именно физически перемещается в новый поток в вашем коде. ### Короткий ответ Когда вы пишете `move ||`, в новый поток перемещается **сама структура замыкания** (closure struct). В вашем случае эта структура имеет размер всего 8 байт (на 64-битной системе) и содержит внутри **только один `Arc`**. ### Подробный разбор ("под капот") #### 1. Что такое замыкание в Rust? Компилятор Rust превращает ваше замыкание в анонимную структуру (struct). Поля этой структуры — это все переменные из внешнего окружения, которые вы захватили. В вашем коде внутри `thread::spawn`: ```rust move || { // Используются: // 1. i (копия, примитив) // 2. chunk_size (копия, примитив) // 3. data_ref (это Arc>) // ... логика } ``` Компилятор генерирует примерно такую структуру: ```rust // Псевдокод сгенерированной структуры struct ClosureEnvironment { i: usize, // 8 байт chunk_size: usize, // 8 байт data_ref: Arc>, // 8 байт (указатель на кучу) } ``` #### 2. Что делает `move`? Ключевое слово `move` приказывает компилятору: "Забери владение всеми переменными, которые используются внутри `{...}`, и положи их в эту структуру `ClosureEnvironment`". Без `move` компилятор попытался бы положить в структуру **ссылки** (`&i`, `&data_ref`), что вызвало бы ошибку компиляции, так как ссылки не могут пережить функцию `sum_squares_static_arc`. #### 3. Что физически "перемещается"? Когда вы вызываете `thread::spawn(move || ...)`: 1. Создается экземпляр этой структуры `ClosureEnvironment` на стеке текущего потока. 2. Этот экземпляр **перемещается** (memcpy) из стека главного потока в стек нового потока (или в кучу, если `Box::new`). * `i` и `chunk_size` просто копируются (как `Copy` типы). * `data_ref` (`Arc`) тоже копируется (бинарно это просто указатель `0x...`). **Сами данные массива `[i32]` никуда не копируются**, они лежат в куче и остаются на месте. Копируется только "умный указатель" на них. ### Итоговая картина В новый поток "улетает" маленький пакет данных (размером 24 байта: `usize` + `usize` + `ptr`), который содержит: 1. Число `i` (индекс потока). 2. Число `chunk_size`. 3. Указатель `Arc` (который увеличил счетчик ссылок на данные, но сами данные не трогал). В этом и есть суть эффективности: вы передаете гигабайты данных в другой поток, физически перемещая всего 8 байт указателя `Arc`. ### Важное уточнение про `Arc` Обратите внимание, что перед циклом вы делаете: ```rust let data_ref = Arc::clone(&data_arc); ``` Именно этот **новый** `data_ref` перемещается в замыкание. Оригинальный `data_arc` остается в `main` потоке нетронутым. Каждая итерация цикла создает свой собственный "билетик" (`data_ref`), и именно этот билетик `move` забирает в новый поток. [1](https://doc.rust-lang.org/std/sync/struct.Arc.html) [2](https://stackoverflow.com/questions/72251938/implement-thread-safe-function-object-in-rust) [3](http://rust-unofficial.github.io/too-many-lists/third-arc.html) [4](https://users.rust-lang.org/t/implementing-thread-safe-structs-for-tokio/21658) [5](https://onesignal.com/blog/thread-safety-rust/) [6](https://www.rustfinity.com/blog/what-is-thread-safety) [7](https://rust-training.ferrous-systems.com/latest/book/thread-safety) [8](https://forums.swift.org/t/arc-automatic-reference-counting-is-thread-safe/63899) [9](https://www.ardanlabs.com/blog/2024/11/fearless-concurrency-ep6-understanding-rust-arc-for-efficient-multithreading.html)