如何在Rust线程间共享可变变量?含Arc/Mutex使用疑问
解决方案:用
Arc<Mutex<T>>实现线程间共享可变变量 原问题核心是多线程无法共享并修改同一个变量,move闭包会转移变量所有权,导致每个线程/闭包拿到独立副本,互相无法感知修改。Arc<Mutex<T>>是Rust中解决这类问题的标准方案:
Arc:原子引用计数,允许多个线程共享同一个值的所有权Mutex:互斥锁,保证同一时间只有一个线程能访问内部值,避免数据竞争
以下是修改后的完整代码:
use std::io::stdin; use std::thread; use std::sync::{Arc, Mutex}; // 新增线程同步工具导入 use enigo::{self, Enigo, MouseControllable}; use enigo::MouseButton; use livesplit_hotkey::*; fn main() { let mut input = String::new(); // 用Arc<Mutex<bool>>包装共享变量,替代原有的mut bool let started = Arc::new(Mutex::new(false)); println!("How many clicks per tick? (too many will lag)"); stdin().read_line(&mut input).expect("Unable to read line"); let input2 = input.trim().parse::<u16>().unwrap(); for _ in 0..input2 { // 每个线程clone一份Arc,获取共享所有权 let started_clone = Arc::clone(&started); thread::spawn(move || { let mut enigo = Enigo::new(); loop { // 锁定Mutex获取内部值的访问权,unwrap处理锁中毒(简单场景下可用) let is_started = *started_clone.lock().unwrap(); if is_started { println!("clicking"); enigo.mouse_click(MouseButton::Left); } // 可选:加小sleep避免线程疯狂占用CPU // thread::sleep(std::time::Duration::from_millis(10)); } }); } println!("Press f8 to toggle clicking"); let hook = Hook::new().unwrap(); // 热键闭包同样clone Arc let started_hook_clone = Arc::clone(&started); hook.register( Hotkey { key_code: KeyCode::F8, modifiers: Modifiers::empty() }, move || { // 锁定Mutex并修改内部值 let mut started_ref = started_hook_clone.lock().unwrap(); *started_ref = !*started_ref; } ).expect("Unable to assign hotkey"); loop {} }
关键改动说明
- 变量包装:用
Arc<Mutex<bool>>替代原有的mut bool,让变量具备多线程共享能力 - 所有权共享:每个线程和热键闭包通过
Arc::clone获取独立的引用计数实例,所有实例指向同一个Mutex包裹的bool值 - 线程安全访问:读写变量前必须调用
lock()获取Mutex锁,确保同一时间只有一个线程操作变量 - 性能优化(可选):在点击循环中加入
thread::sleep,避免线程无休占用CPU资源
内容的提问来源于stack exchange,提问作者HyperCodec
相关产品推荐
相关产品推荐

