在 Rust 中处理多线程的锁

问题描述 投票:0回答:1

我有一个复杂的嵌套结构,它应该通过多线程处理高读/写。 评论:

use std::sync::RwLock;
use std::sync::atomic::AtomicBool;
use once_cell::sync::OnceCell;

#[derive(Default)]
struct Alien {
    info: Info,
    evil: AtomicBool,
}

#[derive(Default)]
struct Info {
    address: String,
}

fn get_alien_instance() -> &'static Alien {
    let alien = Alien::default();
    static INSTANCE: OnceCell<Alien> = OnceCell::new();
    INSTANCE.get_or_init(move || alien)
}

Alien
是具有多个字段和嵌套结构的父结构。将使用
&'static Alien
和内部可变性来改变
Alien
的 mut 字段。我正在讨论嵌套锁和可变性的问题。我想对
Info
结构使用单个(非嵌套)锁,但在其
impl
块内处理其突变。

一个奇怪的解决方案是在

Info
impl 本身中改变
Alien
字段。像这样的东西-

impl Alien {
    fn update_info(&self) {
        let mut info = self.info.write().unwrap();
        info.address = "HEllo".to_string();
    }
}

其他方法是用 Rwlock 包装所有内容。

#[derive(Default)]
struct Alien {
    info: RwLock<Info>,
    evil: AtomicBool,
}

#[derive(Default)]
struct Info {
    address: RwLock<String>,
}

impl Info {
    fn update_address(&self) {
        let mut address = self.address.write().unwrap();
        *address = String::from("Mars");
    }
}

另一种方法是将

RwLockWriteGuard
传递给
Info
impl
。我不知道如何处理这个问题。在管理高读/写的同时,什么是理想的解决方案?

rust locks rwlock interior-mutability
1个回答
0
投票

这对你有帮助吗?这就是我要做的,我认为当您将

Alien.info
作为
RwLock
时,您不需要在 Info 中使用 t
RwLock

use std::sync::{OnceLock, RwLock};

#[derive(Default)]
struct Alien {
    info: RwLock<Info>,
}

static INSTANCE: OnceLock<Alien> = OnceLock::new();

fn get_alien_instance() -> &'static Alien {
    INSTANCE.get_or_init(move || Alien::default())
}

#[derive(Default)]
struct Info {
    address: String,
}

impl Info {
    pub fn update(&mut self, new: String) {
        self.address = new;
    }
}

fn main() {
    std::thread::spawn(|| {
        for s in ["Planet Foo", "Sun Bar", "Baz Galaxy"].iter().cycle().take(10){
            get_alien_instance()
                .info
                .write()
                .unwrap()
                .update(s.to_string());
            std::thread::sleep(std::time::Duration::from_millis(100));
        }
    });

    for _ in 0..100 {
        println!("Address: {}",get_alien_instance().info.read().unwrap().address);
        std::thread::sleep(std::time::Duration::from_millis(10));
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.