Skip to content

并发线程会不有会竞争隐患? #22

@gowy222

Description

@gowy222

之前因为封装过nodejs版本,在无状态云函数和K3S中使用,遇到过并发和初始化冲突问题,所以...源码扔给大模型问了下并发安全问题.

rust不是特别熟,讨论下...

使用 static mut 是不安全的,在多线程环境下可能存在数据竞争
handle_abc 函数中使用了 unsafe 块来访问静态变量
风险: as_mut()获取可变引用,多个线程同时调用会导致数据竞争(Data Race),引发未定义行为。
现实隐患: 代码中通过as_mut()获取可变引用,暗示模型可能维护内部状态(如缓存),而static mut未用Mutex或RwLock保护,破坏了线程安全。

改进建议
使用OnceCell或Lazy: 将全局变量替换为OnceCell或lazy_static,确保初始化仅一次且线程安全。

use once_cell::sync::OnceCell;

static OCR: OnceCell = OnceCell::new();
// 初始化
OCR.get_or_init(|| Ddddocr::new(...));
消除mut: 如果模型无需可变访问,直接通过不可变引用调用方法。

强制Sync: 确保Ddddocr实现Sync trait,或通过Arc<Mutex>包装。


关键问题:参数化初始化与可变性的误用
参数驱动初始化:

代码中模型路径 (ocr_path)、字符集等参数通过命令行动态传入,不同参数需要创建不同的模型实例。

例如,OCR 和 OLD 模型会根据 --ocr-path 参数加载不同的 ONNX 模型和字符集文件。

错误使用 static mut:

static mut OCR: Option<Ddddocr<'static>> 允许全局可变状态,但 Rust 的 static mut 本质上是 非线程安全 的。

初始化时通过 unsafe 块写入全局变量,运行时通过 as_mut() 获取可变引用,这隐含了以下假设:

初始化只发生一次(正确,因为 main 函数只运行一次)。

后续所有并发请求对模型的访问是只读的(错误,as_mut() 强制获取可变引用,暗示可能修改模型状态)。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions