Sharing a read-only thring between threads

As I was trying to work through an example sharing a read-only string among threads.
While it seems the "right" way would be to wrap the string in an Arc::new i was confused by the result of the following code.

I thought this would create 3 copies of the original string for the 3 threads. However if I understand the output correctly I get one copy only.

If I understand correctly using :p we get the address of the variable on the stack and the as_ptr call returns the location of the content of the string in the heap.

So why are the 3 printed from the threads showing the same values?

fn main() {
    let answer = String::from("Hello World!");

    println!("Before:     {answer} {:p} {:?}", &answer, answer.as_ptr());
    for _ in 1..=3 {
        let answer = answer.clone();
        let handle = std::thread::spawn(move || {
            println!(
                "{:?} {} {:p} {:?}",
                std::thread::current().id(),
                answer,
                &answer,
                answer.as_ptr()
            );
        });
        handle.join().unwrap();
    }
    println!("After:      {answer} {:p} {:?}", &answer, answer.as_ptr());
}
Before:     Hello World! 0x7ffec81bf918 0x5c8c20f18b80
ThreadId(2) Hello World! 0x7b2f151ffb70 0x5c8c20f18ba0
ThreadId(3) Hello World! 0x7b2f151ffb70 0x5c8c20f18ba0
ThreadId(4) Hello World! 0x7b2f151ffb70 0x5c8c20f18ba0
After:      Hello World! 0x7ffec81bf918 0x5c8c20f18b80

Your threads run serially and free the String at the end, allowing the allocator to reuse the same memory.

Add answer.leak() to the thread closure to see a difference.

2 Likes

Oh I think I mistakenly put the join inside the for loop and if I understand correctly that makes these threads run serially, right?

yes

thanks

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.