How does rustc know a variable is in a "multi-thread" situation?

I wondered how is rust's thread safety was implemented, for example:

fn main() {
    let i = Rc::new(1);
    let ci = i.clone();
    let labda = move || {
        ci;
    };
}

code above don't have thread safety waring, but code like this:

fn main() {
    let i = Rc::new(1);
    let ci = i.clone();
    std::thread::spawn(move || {
        ci;
    });
}

will trigger the sync trait checking, which means the compiler knows that ci is in a new thread.

Is there any magic here? Or just because compiler "see" the code std::thread? What if I use something like posix thread libraries(don't find a safe crate, just for example), will the compiler aware multi-thread context as well?

No real magic. Let's look at the docs for std::thread::spawn. This function specifies a trait bound on the closure, it says F: Send + 'static and that's basically the thing that does it.

What is a closure? It's a combination of captures and a function to call. What does F: Send + 'static really mean? Functions, code to call, in inline closures, are always Send + 'static so this bound ends up applying to "just" the captures of the closure.

3 Likes

Well, that's it? I'm a little disappointing :rofl:

I seem to understand why we can implement sync on types, but it is unsafe...

Yeah, implementing Send/Sync on your types is something you can do only if you're really ready to assert/promise that your type really will uphold the required thread safety properties. It's easier to construct the type from primitives that already do this correctly so that no explicit Send/Sync implementations are needed.

For Rc for example, you'd look towards using Arc instead.

1 Like

Is there anything special with trait Sync? I mean does compiler treat it as other normal traits? For example compiler check all captures which must be Sync as well, which do not apply for normal traits?

Or, in other word, does code

pub fn test<F>(f: F)
    where F: Foo + 'static {}

makes any sense? (I never see code like this, and I don't know if I can implement a triat for a closure either)

I'm asking this because I'm writing codes to execute commands on GPU, there's a concept called queue, which is similar to a "thread", I'm wondering if I can create something like Sync to make GPU commands safe, too.

Sync/Send are special in the sense that they are auto traits, not really regular traits. I guess looking at all of chapter 16 is a good start, it's an overview Fearless Concurrency - The Rust Programming Language Maybe someone else has good input on how to apply it to GPUs

2 Likes

Looks like the first step to do this is to wait the auto_trait feature complished...

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.