如何将只读数据发送到其他线程而不进行复制?

2023-12-19

我正在尝试将只读数据的“视图”发送到另一个线程进行处理。基本上主线程确实工作,不断更新一组数据。每当发生更新时,主线程应该将更新的数据发送到其他线程,在那里它们将以只读方式处理它。我不想复制数据,因为它可能非常大。 (无论如何,主线程还在内存中保留数据的“缓存”。)

我可以通过以下方式实现这一点Arc<RwLock<T>>, where T是我的数据结构。

但是,没有什么可以阻止侧线程更新数据。侧线程可以简单地调用lock()以及写入数据。

我的问题是有类似的东西RwLock它的所有者/创建者具有唯一的写入访问权限,但所有其他实例都具有只读访问权限?这样,我将在编译时检查可能通过侧线程意外更新数据而发生的任何逻辑错误。

关于这些问题:

  • Rust 中的线程之间共享只读对象? https://stackoverflow.com/questions/51804379/sharing-read-only-object-between-threads-in-rust

  • 如何将对堆栈变量的引用传递给线程? https://stackoverflow.com/questions/32750829/how-can-i-pass-a-reference-to-a-stack-variable-to-a-thread

上述问题建议用以下方法解决Arc<Mutex<T>> or Arc<RwLock<T>>一切都很好。但它仍然不能只执行一个编写者的编译时操作。

此外:crossbeam or rayon的作用域线程在这里没有帮助,因为我希望我的副线程比我的主线程寿命更长。


您可以创建一个包装类型Arc<RwLock<T>>仅通过只读包装器公开克隆:

mod shared {
    use std::sync::{Arc, LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard};

    pub struct Lock<T> {
        inner: Arc<RwLock<T>>,
    }

    impl<T> Lock<T> {
        pub fn new(val: T) -> Self {
            Self {
                inner: Arc::new(RwLock::new(val)),
            }
        }

        pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> {
            self.inner.write()
        }

        pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> {
            self.inner.read()
        }

        pub fn read_only(&self) -> ReadOnly<T> {
            ReadOnly {
                inner: self.inner.clone(),
            }
        }
    }

    pub struct ReadOnly<T> {
        inner: Arc<RwLock<T>>,
    }

    impl<T> ReadOnly<T> {
        pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> {
            self.inner.read()
        }
    }
}

现在,您可以将值的只读版本传递给生成的线程,并继续在主线程中写入:

fn main() {
    let val = shared::Lock::new(String::new());

    for _ in 0..10 {
        let view = val.read_only();
        std::thread::spawn(move || {
            // view.write().unwrap().push_str("...");
            // ERROR: no method named `write` found for struct `ReadOnly` in the current scope
            println!("{}", view.read().unwrap());
        });
    }

    val.write().unwrap().push_str("...");
    println!("{}", val.read().unwrap());
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将只读数据发送到其他线程而不进行复制? 的相关文章

随机推荐

  • 如何调用 Start-Job,它依赖于与调用 Start-Job 的函数位于同一 powershell 模块中的函数?

    我正在单个模块中编写一些 powershell 来与 AWS API 对话 我写了一个函数 Get CloudFormation 它返回 CloudFormation 的状态 我写了另一个函数 Delete CloudFormation 在
  • 未为加载的控件生成 ASP.NET 客户端 ID

    我在 updatepanel 中有一个 UserControl AddressInfoGroup 它通过 loadControl 方法动态加载用户控件 AddressInfo 我在同一页面上还有另外两个这样的控件 它们都可以正常工作 当 A
  • 为什么 32 位整数的左移位“<<”在使用超过 32 次时不能按预期工作?

    当我编写以下程序并使用 GNU C 编译器时 输出为1我认为这是由于编译器执行的旋转操作造成的 include
  • 带有 PDF 的新标签 - 下载按钮在 Chrome 上不起作用

    当用户单击按钮时 我向服务器发送请求 然后服务器发回 pdf base64 然后我在新选项卡中打开它 但下载按钮来自Chrome预览不起作用 当我单击它时没有任何操作 它在 Firefox 上运行良好 Chrome预览下载按钮 定义变量if
  • Oracles 'alter system set local_listener' 到底做了什么

    为什么我很好奇 我在安装 Oracle Express 数据库时总是遇到问题 因为我从来没有第一次就成功过 安装 Oracle Express 后下次启动计算机时 我始终收到常见错误 https stackoverflow com ques
  • LINQ to XML:上下移动节点的最有效方法是什么

    我需要在某些节点之前和之后移动同级节点 这是我正在使用的代码
  • 如何读取 Mahout 聚类输出

    我已经对 Mahout 教程中的合成控制数据运行了 k 均值聚类算法 并且想知道是否有人可以解释如何解释输出 我运行 clusterdump 并收到如下所示的输出 被截断以节省空间 CL 592 n 57 c 30 726 29 813 r
  • 长时间偶然的 Young 垃圾收集暂停

    我们调整 GC 以最小化 stop the world 暂停 Perm 和 Tenured 一代表现良好 Young在大多数情况下工作正常 暂停通常不超过500ms 注意 Times user 0 35 sys 0 02 real 0 06
  • 更新 iPhone 应用程序行为

    我为iPhone设备开发了一款与数据库相关的应用程序 SQlite数据库 现在我想用更多功能更新该应用程序 我想推送同一应用程序的更新 在这里 我在推送更新时更关心用户数据 所以我的问题是 如果我将推送更新 那么更新是否会清除 sqlite
  • 关于 C++ 中的结构化异常 (SEH),我应该了解哪些信息?

    每个 C 开发人员都应该了解有关结构化异常的哪些要点 它们是相当于 Unix 信号的 Win32 可以让您捕获 CPU 异常 例如访问冲突 非法指令 除零等 使用正确的编译器选项 对于 Visual C 为 EHa C 异常使用与堆栈展开相
  • 如何使用 Apache MINA SSHD 阻止 SFTP 删除操作

    我正在尝试使用 Apache Mina SSHD 创建自定义 sftp 服务器 到目前为止我的代码 SshServer sshd SshServer setUpDefaultServer sshd setPort PORT NUMBER s
  • 在数据库中插入数据集记录

    我需要将数据集记录 C 插入 MS Access 数据库表中 我需要批量插入记录 我怎样才能在 C 中做到这一点 对于此类任务 请考虑使用数据适配器 http msdn microsoft com en us library system
  • Prometheusmetrics_path 中的问号被编码

    由于 Prometheus 仅支持文本指标和许多工具返回 json 格式的指标 如 Finatra Spring Boot 因此我创建了一个简单的代理 它将 json 转换为文本 因为我想将它用于多个源 所以要从中检索实际指标的目标是通过查
  • Websocket 消息是否会无序到达?

    如果我们通过同一个 html5 websocket 发送两条消息 彼此间隔毫秒 理论上 消息到达的顺序是否可能与发送的顺序不同 简短回答 不 长答案 WebSocket 通过 TCP 运行 因此在该级别上 EJP 的答案适用 WebSock
  • 运行应用程序脚本后,Google 电子表格冻结

    我的 Google 电子表格中附加了一个应用程序脚本 有一个函数可以在电子表格中执行很多操作 这就是它的作用 创建一个新工作表 设置新工作表的列标题 将数据复制到新工作表中 设置公式 删除多余的列 删除多余的行 在现有工作表中添加一行 工作
  • 指定并保存精确尺寸(以像素为单位)的图形

    假设我有一张尺寸为 3841 x 7195 像素的图像 我想将图形的内容保存到磁盘 从而生成一个图像精确尺寸我以像素为单位指定 没有轴 没有标题 只是图像 我个人并不关心 DPI 因为我只想指定图像在屏幕中在磁盘中所占的大小以像素为单位 我
  • Google 将自动完成功能设置为在 Windows 移动版 IE 浏览器中不起作用

    我们正在为我们的产品建立一个移动网站ridingo http www ridingo com 我们在我们的网站上广泛使用谷歌地点自动完成功能 这用于在用户键入时向他们提供建议 我们在多个浏览器和设备上对此进行了测试 这在 Android 设
  • Android 意图输入 Google Play 音乐应用程序的搜索查询

    您好 我正在尝试使用我的应用程序提供的字符串自动填充 Google Play 音乐上的搜索栏 我目前打算打开 Google Play 音乐 但我无法找到正确的参数来填充 Google Play 音乐上的搜索栏 这是我的代码 Intent i
  • Android webview 性能缓慢

    我正在用 javascript 编写一个游戏 这个应用程序在我的浏览器上运行良好 速度很快 但我在使用 android webview 运行它时遇到了一些麻烦 启动应用程序需要 5 秒或更长时间 我认为这有点慢 但也许这是正常的 在游戏菜单
  • 如何将只读数据发送到其他线程而不进行复制?

    我正在尝试将只读数据的 视图 发送到另一个线程进行处理 基本上主线程确实工作 不断更新一组数据 每当发生更新时 主线程应该将更新的数据发送到其他线程 在那里它们将以只读方式处理它 我不想复制数据 因为它可能非常大 无论如何 主线程还在内存中