Search code examples
rustrust-tokio

Why does tokio::spawn not require Sync?


The doc says

The spawned task may execute on the current thread, or it may be sent to a different thread to be executed.

So if you share a variable which is !Sync between two async blocks and spawn them, they may be executed simultaneously, which induces race condition.

How does tokio deal with it?


Solution

  • Spawning an async task (future) requires that it is Send. If two futures share access to something that is not Sync, then the future itself will not be Send. This is not something specific to Tokio or to async; notice that std::thread::spawn has the same requirement of Send + 'static on the spawned function.

    The way this works is that anything that allows access to a value from multiple threads (such as Arc or &) will have a conditional implementation for Send like this one (from the standard library code for Arc):

    unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
    

    This says: An Arc<T> will not be Send unless its contents T are Sync.

    Anything you can find that will allow you to “share a variable” will similarly enforce that the data that is shared must be Sync.