You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Tauri时Unicorn结构体跨线程安全问题求助

解决Unicorn结构体作为Tauri全局变量的线程安全问题

编译错误信息

error[E0277]: `Rc<UnsafeCell<UnicornInner<'static, ()>>>` cannot be sent between threads safely
  --> src\main.rs:76:37
   |
76 | fn init_emulator(emulator_instance: State<EmulatorGlobal>) {
   |                                     ^^^^^^^^^^^^^^^^^^^^^ `Rc<UnsafeCell<UnicornInner<'static, ()>>>` cannot be sent between threads safely
   |
   = help: within `Unicorn<'static, ()>`, the trait `Send` is not implemented for `Rc<UnsafeCell<UnicornInner<'static, ()>>>`
   = note: required because it appears within the type `Unicorn<'static, ()>`
   = note: required for `std::sync::Mutex<Unicorn<'static, ()>>` to implement `Send`
note: required because it appears within the type `EmulatorGlobal`
  --> src\main.rs:27:8
   |
27 | struct EmulatorGlobal(Mutex<Unicorn<'static, ()>>);
   |        ^^^^^^^^^^^^^^
note: required by a bound in `State`
  --> C:\Users\Aslan\.cargo\registry\src\github.com-1ecc6299db9ec823\tauri-1.2.2\src\state.rs:14:25
   |
14 | pub struct State<'r, T: Send + Sync + 'static>(&'r T);
   |                         ^^^^ required by this bound in `State`

相关结构体与代码

第三方crate的Unicorn结构体定义:

/// A Unicorn emulator instance.
pub struct Unicorn<'a, D: 'a> {
    inner: Rc<UnsafeCell<UnicornInner<'a, D>>>,
}

Tauri全局变量声明:

struct EmulatorGlobal(Mutex<Unicorn<'static, ()>>);

Tauri命令代码:

#[tauri::command]
fn init_emulator(emulator_instance: State<EmulatorGlobal>) {
    let mut unicorn: Unicorn<()> = Unicorn::new(Arch::X86, Mode::MODE_64).expect("ERROR");
}

注:该结构体使用的是alloc::rc::Rc,功能与std::rc::Rc一致

安全的猴子补丁解决方案

问题核心是Unicorn因内部Rc未实现Send,无法满足Tauri全局状态的Send + Sync约束。我们可以通过包装结构体手动实现线程安全trait,前提是通过Mutex保证互斥访问:

// 定义包装结构体,封装Unicorn实例
struct ThreadSafeUnicorn(Unicorn<'static, ()>);

// 手动实现Send和Sync
// 安全性说明:通过Mutex确保同一时间只有一个线程访问Unicorn实例,
// 内部Rc不会被跨线程clone,UnsafeCell的操作处于互斥保护下,因此是安全的
unsafe impl Send for ThreadSafeUnicorn {}
unsafe impl Sync for ThreadSafeUnicorn {}

// 修改全局变量定义,使用包装后的结构体
struct EmulatorGlobal(Mutex<ThreadSafeUnicorn>);

// 更新Tauri命令代码
#[tauri::command]
fn init_emulator(mut emulator_instance: State<EmulatorGlobal>) {
    let unicorn = Unicorn::new(Arch::X86, Mode::MODE_64).expect("ERROR");
    // 将实例存入全局变量
    *emulator_instance.0.lock().unwrap() = ThreadSafeUnicorn(unicorn);
}

关键说明

  • Mutex提供了线程间的互斥访问保证,避免多线程同时操作UnsafeCell的风险
  • Rc本身不支持跨线程传递,但我们不会跨线程clone这个Rc,只会在同一线程内通过Mutex锁定后访问,因此引用计数操作是线程安全的
  • 手动实现Send和Sync是unsafe操作,但基于上述约束,这个实现是安全的

内容的提问来源于stack exchange,提问作者swapgs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 19:30:38