Sharing a reference to an instance of trait between threads

后端 未结 2 1116
北荒
北荒 2021-01-01 19:24

I am playing with Rust\'s concurrency and trying to wrap my head around Send/Sync/Arc/Mutex. I have problems with sharing

2条回答
  •  伪装坚强ぢ
    2021-01-01 20:21

    Remember that types of original values which are converted to trait objects are erased. Therefore, the compiler can't know whether the data inside the Arc is Send and Sync, and without these traits sharing data across threads may be unsafe. You need to specify that types which can be stored in Arc must be Send and Sync:

    let mut map: HashMap> = HashMap::new();
    

    (try it here)

    The Send bound is required by thread::spawn(), and Sync is required by Arc for it to be Send. Additionally, thread::spawn() also requires 'static but it is implicit in this particular Arc type declaration.

    Of course, you will be able to store only Sync and Send implementations of Foo, but this is necessary to ensure memory safety. However, in Rust synchronization is implemented with wrappers like Mutex or RwLock. They don't implement Foo even if T implements Foo, therefore you won't be able to store, say, Mutex inside your map (unless Foo is your trait and you implemented it for Mutex, which could be unwieldy), which would be necessary if your Foo implementations are not Sync but Send (though I'm not sure I can provide an example of such type now).

    To solve this you'd need to change map type to contain a mutex inside it explicitly:

    let mut map: HashMap>> = HashMap::new();
    

    This way, there is no need for the Sync bound because Mutex is Sync if its contents are Send.

    And naturally, you won't be able to share Foo implementations which are not Send at all, and there is no way around it. This can happen, for example, if Foo's implementation contains Rcs.

提交回复
热议问题