首页 > 解决方案 > Rust Arc 如何获取_mut 并在此之后恢复其他 Arc 副本的读取能力?

问题描述

我想知道如何更改内部的值Arc,然后Arc再次制作有效的其他副本。

use std::sync::Arc;
use std::thread;
use std::error::Error;
use std::io;
use std::time::Duration;

#[derive(Debug)]
struct El {
  n: i64,
}

fn main() -> io::Result<()> {
  let mut a = Arc::new(El{n: 5});
  let b = Arc::clone(&a);
  let th = thread::spawn(move || {
    println!(r#"Hello, World!"#);
    thread::sleep(Duration::from_millis(1000));
    println!("{:?}", b);
  });
  let mut c = Arc::get_mut(&mut a).unwrap();
  c.n = 10;
  drop(c);
  drop(a);
  th.join().expect("some errors occured");
  Ok(())
}

当突变已经完成并且指针被丢弃时,这将导致恐慌。如何解决?

标签: rust

解决方案


您想在一个线程中写入内容并Arc在另一个线程中读取它。在 Rust 中,一个值要么是共享可读的,要么是独占可写的。具有多个参考的圆弧是共享的。

您可以通过使用内部可变性来解决此问题,例如 viaArc<Mutex<El>>Arc<RwLock<El>>MutexRwLock通过阻塞所有读取直到写入完成并在读取锁存在时阻塞所有写入来动态确保共享/排他约束。

例子:

fn main() -> io::Result<()> {
  let a = Arc::new(Mutex::new(El{n: 5}));
  let b = Arc::clone(&a);
  let th = thread::spawn(move || {
    println!(r#"Hello, World!"#);
    thread::sleep(Duration::from_millis(1000));
    println!("{:?}", b.lock().unwrap());
  });
  a.lock().unwrap().n = 10;
  drop(a);
  th.join().expect("some errors occured");
  Ok(())
}

推荐阅读