简体   繁体   English

为什么我可以在Rust中将static&str“移动”到多个线程中?

[英]Why can I “move” a static &str into multiple threads in Rust?

I'd like to better understand the semantics behind the following Rust code: 我想更好地理解以下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();
}

I do not understand why this code compiles. 我不明白为什么要编译此代码。 I have shared the variable mutable between multiple threads and even mutated it. 我已经共享了可变mutable多个线程之间,甚至突变它。 What exactly is going on behind-the-scenes with the memory here? 内存在幕后到底发生了什么? Are we making multiple pointers to the same string in static memory? 我们是否在静态内存中使多个指针指向同一字符串? Are we placing two different static strings in memory? 我们是否在内存中放置了两个不同的静态字符串? The fact that I can have two threads reading from the same immutable item doesn't surprise me, but having two threads reading from a mutable variable does. 我可以让两个线程从同一个不可变项中读取数据,这一事实并不令我感到惊讶,但是让两个线程从一个可变变量中读取数据确实令我惊讶。

Note that even if thread 3 runs before 4, 4 does not reflect the updated string that thread 3 sets in its println! 请注意,即使线程3在4之前运行,4也不反映线程3在其println!设置的更新字符串println! statement. 声明。 Finally, since I didn't pass using &immutable , does this mean that the value is being "moved" into each thread rather than the actual memory address? 最后,由于我没有使用&immutable ,这是否意味着该正在“移动”到每个线程中,而不是实际的内存地址中?

I have shared the same variable mutable between multiple threads and even mutated it. 我在多个线程之间共享了相同的可变变量,甚至对其进行了突变。

No, you have copied a reference to the same static string into multiple threads. 不,您已将对同一静态字符串的引用复制到多个线程中。 The reference points to a constant static string which can't be mutated. 该引用指向一个不变的静态字符串,该字符串不能被突变。 Read-only references are Copy , so you can move them into multiple closures. 只读引用是Copy ,因此您可以将它们移动到多个闭包中。

What exactly is going on behind-the-scenes with the memory here? 内存在幕后到底发生了什么?

A string slice is essentially a pointer to the beginning of a string in memory together with a length. 字符串切片实际上是指向内存中字符串开头以及长度的指针。 Your variables mutable and immutable only contain these two pieces of information, and only these pieces are mutable for mutable . 您的变量mutableimmutable只包含这两种信息,并且只有这些作品是可变的mutable The actual strings the variables point to are immutable. 变量指向的实际字符串是不可变的。 When "moving" the variables into the closures, they are actually copied, since &str is Copy . 当将变量“移动”到闭包中时,实际上会复制它们,因为&strCopy The only information that is copied is the pointer and the length, not the actual string data. 复制的唯一信息是指针和长度,而不是实际的字符串数据。 You end up with multiple pointers to the same read-only memory, which doesn't allow for any data races and conforms to Rust's memory safety rules. 您最终会获得指向同一只读内存的多个指针,这不允许任何数据争用并且符合Rust的内存安全规则。

Also, note that even if thread 3 runs before 4, 4 does not reflect the updated string that thread 3 sets in its println! 另外,请注意,即使线程3在4、4之前运行,也不会反映线程3在其println中设置的更新字符串! statement. 声明。

You only modify the copy of the pointer and the length. 您仅修改指针的副本和长度。 In thread 3, mutable becomes a separate variable local to the closure, and you only modify that. 在线程3中, mutable变量成为闭包局部的一个单独变量,您只需对其进行修改。

Finally, since I didn't pass using &immutable , does this mean that the value is being "moved" into each thread rather than the actual memory address? 最后,由于我没有使用&immutable ,这是否意味着该值正在“移动”到每个线程中,而不是实际的内存地址中?

The variable immutable has the type &'static str , so it is already a reference; immutable变量的类型为&'static str ,因此它已经是一个引用; &immutable would be a reference to a reference. &immutable将是对引用的引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM