【问题标题】:What are examples of types that implement only one of Send and Sync?仅实现 Send 和 Sync 之一的类型示例有哪些?
【发布时间】:2016-03-05 00:10:08
【问题描述】:

为了更好地理解 SendSync 特征,是否有以下类型的示例:

  • 实现Send,不实现Sync
  • 实现Sync,不实现Send

【问题讨论】:

  • Huon Wilson's article on Send and Sync 提到了一个假设的垃圾收集指针Gc<T>,可能是Sync,但不是Send,尽管他没有详细说明。
  • @JackO'Connor:给你;)
  • @MatthieuM 谢谢! :)

标签: rust


【解决方案1】:

首先,重要的是要意识到大多数结构(或枚举)都是Send

  • 任何不包含任何引用的结构都可以是Send + 'static
  • 任何包含下界生命周期为'a 的引用的结构都可以是Send + 'a

因此,您通常会期望任何 Sync struct 也是 Send,因为 Send 是一个非常容易到达的栏(与更难的 Sync 相比,它需要来自多个线程的安全并发修改)。


但是,没有什么能阻止类型的创建者专门将其标记为不是Send。例如,让我们恢复条件!

在 Lisp 中,条件的概念是您为给定条件设置一个处理程序(例如:FileNotFound),然后当在堆栈深处满足该条件时,您的处理程序就会被调用。

你将如何在 Rust 中实现这一点?

为了保持线程的独立性,您可以为条件处理程序使用线程本地存储(请参阅std::thread_local!)。每个条件都是一个堆栈的条件处理程序,要么只调用顶部的一个,要么从顶部开始一个迭代过程,直到一个成功为止。

那么,你会如何设置它们呢?

就个人而言,我会使用 RAII!我会在线程本地堆栈中绑定条件处理程序并将其注册到框架中(例如,使用侵入式双向链表作为堆栈)。

这样,当我完成后,条件处理程序会自动取消注册。

当然,系统必须考虑用户做意外的事情(比如将条件处理程序存储在堆中,而不是按照它们创建的顺序删除它们),这就是我们使用双向链表的原因,所以处理程序可以在必要时从堆栈中间取消注册。

所以我们有一个:

struct ConditionHandler<T> {
    handler: T,
    prev: Option<*mut ConditionHandler<T>>,
    next: Option<*mut ConditionHandler<T>>,
}

“真正的”处理程序由用户作为T 传递。


这个处理程序是Sync吗?

可能,取决于您如何创建它,但您没有理由不能创建一个处理程序,从而无法在多个线程之间共享对它的引用。

注意:这些线程无法访问其 prev/next 数据成员,这些成员是私有的,不必是 Sync

这个处理程序是Send吗?

除非特别注意,否则不会。

prevnext 字段不受并发访问保护,如果在另一个线程获得对它的引用时删除处理程序(例如,另一个处理程序试图取消注册自己),则更糟糕的是) 那么这个现在悬空的引用将导致未定义的行为。

注意:后一个问题意味着仅仅将Option&lt;*mut Handler&lt;T&gt;&gt; 切换为AtomicPtr&lt;ConditionHandler&lt;T&gt;&gt; 是不够的;有关详细信息,请参阅Common Pitfalls in Writing Lock-Free Algorithms


你有它:如果TSync,则ConditionHandler&lt;T&gt;Sync,但永远不会是Send(原样)。

为了完整起见,许多类型实现了Send,但没有实现Sync(实际上大多数Send 类型):例如OptionVec

【讨论】:

  • 让我们恢复条件! - 你是一个疯狂的疯狂的人。我喜欢它。
【解决方案2】:

CellRefCell 实现 Send 但不是 Sync,因为它们可以在线程之间安全发送,但不能在它们之间共享。

【讨论】:

  • 这是不正确的,AtomicIsize 等确实实现了发送。它没有在文档页面上列出,因为实现是自动派生的,与必须为它们显式派生的 Sync 不同。然而,一个简单的let v: &amp;Send = &amp;AtomicIsize::new(5); 表明他们实现了发送。
  • 我已经删除了@wingedsubmariner 指出的错误部分。
  • 可以直接查看类型是否实现了traits (play example)
猜你喜欢
  • 2012-01-17
  • 2012-02-28
  • 2013-08-29
  • 2015-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-23
  • 2011-07-16
相关资源
最近更新 更多