How can I guarantee that a type that doesn't implement Sync can actually be safely shared between threads?

前端 未结 2 1684
甜味超标
甜味超标 2020-12-04 02:09

I have code that creates a RefCell and then wants to pass a reference to that RefCell to a single thread:

use cros         


        
相关标签:
2条回答
  • 2020-12-04 02:31

    One way would be to use a wrapper with an unsafe impl Sync:

    use crossbeam; // 0.7.3
    use std::cell::RefCell;
    
    fn main() {
        struct Wrap(RefCell<i32>);
        unsafe impl Sync for Wrap {};
        let val = Wrap(RefCell::new(1));
    
        crossbeam::scope(|scope| {
            scope.spawn(|_| *val.0.borrow());
        })
        .unwrap();
    }
    

    As usual with unsafe, it is now up to you to guarantee that the inner RefCell is indeed never accessed from multiple threads simultaneously. As far as I understand, this should be enough for it not to cause a data race.

    0 讨论(0)
  • 2020-12-04 02:36

    Another solution for this case is to move a mutable reference to the item into the thread, even though mutability isn't required. Since there can be only one mutable reference, the compiler knows that it's safe to be used in another thread.

    use crossbeam; // 0.7.3
    use std::cell::RefCell;
    
    fn main() {
        let mut val = RefCell::new(1);
        let val2 = &mut val;
    
        crossbeam::scope(|scope| {
            scope.spawn(move |_| *val2.borrow());
        })
        .unwrap();
    }
    

    As bluss points out:

    This is allowed because RefCell<i32> implements Send.

    0 讨论(0)
提交回复
热议问题