我正在编写一个WebSocket服务器,其中一个Web客户端连接到多线程计算机AI上下棋.WebSocket服务器想要将Logger对象传递给AI代码.该Logger对象将管理从AI到Web客户端的日志行.在Logger必须包含对客户端连接的参考.
我对生命周期如何与线程交互感到困惑.我用Wrapper类型参数化的结构重现了这个问题.该run_thread函数尝试解包该值并记录它.
use std::fmt::Debug;
use std::thread;
struct Wrapper<T: Debug> {
val: T,
}
fn run_thread<T: Debug>(wrapper: Wrapper<T>) {
let thr = thread::spawn(move || {
println!("{:?}", wrapper.val);
});
thr.join();
}
fn main() {
run_thread(Wrapper::<i32> { val: -1 });
}
Run Code Online (Sandbox Code Playgroud)
该wrapper参数存在于堆栈中,并且它的生命周期不会延伸超过run_thread堆栈帧,即使该线程将在堆栈帧结束之前连接.我可以从堆栈中复制值:
use std::fmt::Debug;
use std::thread;
struct Wrapper<T: Debug + Send> {
val: T,
}
fn run_thread<T: Debug + Send + 'static>(wrapper: Wrapper<T>) {
let thr = thread::spawn(move || …Run Code Online (Sandbox Code Playgroud) 我有代码创建一个RefCell然后想要将它的引用传递RefCell给单个线程:
extern crate crossbeam;
use std::cell::RefCell;
fn main() {
let val = RefCell::new(1);
crossbeam::scope(|scope| {
scope.spawn(|| *val.borrow());
});
}
Run Code Online (Sandbox Code Playgroud)
在完整的代码中,我使用的是一种RefCell嵌入其中的类型(a typed_arena::Arena).我正在使用crossbeam来确保线程不会超过它所引用的引用.
这会产生错误:
error: the trait bound `std::cell::RefCell<i32>: std::marker::Sync` is not satisfied [E0277]
scope.spawn(|| *val.borrow());
^~~~~
Run Code Online (Sandbox Code Playgroud)
我相信我理解为什么会发生这样的错误:RefCell不是设计为从多个线程同时调用,并且因为它使用内部可变性,所以需要单个可变借位的正常机制不会阻止多个并发操作.这甚至记录在Sync:
不属于类型
Sync是那些具有"室内易变性"在非线程安全的方式,比如Cell和RefCell中std::cell.
这一切都很好,但在这种情况下,我知道只有一个线程能够访问RefCell.我怎样才能向编译器确认我理解我在做什么,我确保是这样的?当然,如果我认为这实际上是安全的是不正确的,我会非常乐意被告知原因.