【问题标题】:Passing around a reference to a struct in Rust在 Rust 中传递对结构的引用
【发布时间】:2020-11-29 10:58:34
【问题描述】:

我的问题基本上是在我的程序中,我需要将对 s 结构的引用传递到多个地方,包括一个新线程。例如,在 C 语言中,我可以将它声明为一个全局结构并以这种方式使用它。 如何在 rust 中做到这一点?

对于某些代码,我还需要使用 RefCell 包裹在 Rc 中(我之前的问题)。

fn a_thread(s: &SomeStruct) {

//... code using s reference ... //

}

struct SomeStruct {
    val: bool,
}

fn main() {
    let mut s = SomeStruct { val: true };

    let s_rc = Rc::new(RefCell::new(s));
    thread::spawn(move || a_thread(&s)); // <= error: use of moved value 's'
    
    
    //... code using the s_rc ... //
    

}



【问题讨论】:

  • a_thread()需要修改s吗?共享参考真的可以吗?
  • 此外,显示的代码也不适用于单线程代码(RcRefCell),因为您试图将 s 移动到闭包中,而不是 @987654330 @.
  • a_thread() 只需要从结构中读取值。我想从主线程修改结构

标签: struct rust reference refcell


【解决方案1】:

如果一个线程修改数据而另一个线程读取它,则必须同步,否则就会出现数据竞争。 Safe Rust 通过静态分析防止数据竞争,因此它不允许您获得 &amp;SomeStruct,而底层值可能被另一个线程修改。

你可以做的是使用互斥体代替RefCell,使用Arc代替Rc

fn a_thread(s: Arc<Mutex<SomeStruct>) {
    // when you need data from s:
    {
        let s = s.lock().unwrap();
        // here you can read from s, or even obtain a `&SomeStruct`
        // but as long as you hold on to it, the main thread will be
        // blocked in its attempts to modify s
    }
}

fn main() {
    // create s on the heap
    let s = Arc::new(Mutex::new(SomeStruct { val: true }));

    // cloning the Arc creates another reference to the value
    let s2 = Arc::clone(&s);
    thread::spawn(move || a_thread(s2));
    
    //... code using s ... //
    {
        let s = s.lock().unwrap();
        // here you can modify s, but reading will be blocked
    }
}

【讨论】:

  • 由于只有一个线程需要修改值,RwLock 不是在这里工作得更好吗?
  • @RedBorg 它的工作原理是一样的,因为读者和作者仍然会相互锁定。上次我测量时,获得无争议的RwLock 比获得Mutex 更昂贵,因为它的簿记更复杂。当RwLock 真正提供好处时,应该使用它:当数据位于Mutex 后面时,有多个读取器会相互锁定。
  • @user4815162342 当然,对于单线程,它会更昂贵。我以为会有多个线程都在看同一个值,我的错。
猜你喜欢
  • 2021-08-16
  • 2020-10-20
  • 2023-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多