我正在生成一个线程,它构建的本质上是一棵树,稍后需要它,因此可以在线程外计算。举个例子,想想Foo { inner: HashMap<Bar, Rc<FooBar>> }
。线程的关闭不会从周围环境捕获任何东西。
问题是Rc
使整个类型成为!Send
。这阻止了Foo
返回到生成线程。实际上,Rc
“毒害”了Foo
。
我不明白为什么由派生线程创建并返回的类型仍然需要是Send
的原因:它强制所有内部类型(在这种情况下,Rc
中的HashMap
,在Foo
,变为 Send
。从衍生线程的角度来看,这是无法修复的。
它强制生成的线程始终使用原子计数,而实际上两个线程同时访问引用计数器的可能性为零。
有没有办法从线程返回(不是共享!)包含Rc
的类型?我是否遗漏了对Send
的理解?
最佳答案
[T]here is actually zero possibility for both threads to access the refcounter simultaneously.
但是编译器无法理解,所以您必须说“不,真的,相信我,我知道它看起来很狡猾,但实际上是安全的。”这就是 unsafe
的用途。
应该很简单
unsafe impl Send for Foo {}
来自Nomicon :
Rc
isn't Send or Sync (because the refcount is shared and unsynchronized).
让 Rc
本身 Send
是不安全的,因为 Rc
暴露了一个接口(interface),如果在线程之间发送是不安全的。但是 Foo
,正如您所描述的那样,公开了一个接口(interface),该接口(interface)不是在线程之间发送是不安全的,所以只需 unsafe impl
它并继续你的方式。
假设,也就是说,接口(interface)是可以安全地在线程之间发送。例如,Foo
不能有克隆并返回内部 Rc
的方法(因为您可以使用它有效地“走私”一个裸露的 Rc
通过 Foo
进入另一个线程。
如果 Foo
并非始终 安全发送,但您碰巧知道某些特定 Foo
是安全发送,更好的方法是暂时将其包装在 Send
类型中,如 Shepmaster's answer建议。
关于multithreading - 如何从线程返回包含 Rc 的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54446633/