仅实现 Send 和 Sync 之一的类型示例有哪些? [英] What are examples of types that implement only one of Send and Sync?

查看:41
本文介绍了仅实现 Send 和 Sync 之一的类型示例有哪些?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Just to get better understanding of the Send and Sync traits, are there examples of types that either:

  • 实现Send,不实现Sync.
  • 实施Sync,不实施Send.
  • Implement Send and do not implement Sync.
  • Implement Sync and do not implement Send.

推荐答案

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

First of all, it is important to realize that most structs (or enums) are Send:

  • 任何不包含任何引用的结构体都可以是Send + 'static
  • 任何包含生命周期下限为 'a 的结构体都可以是 Send + 'a
  • any struct that does not contain any reference can be Send + 'static
  • any struct that contain references with a lower-bound lifetime of 'a can be Send + 'a

因此,您通常希望任何 Sync struct 也是 Send,因为 Send 是如此容易达到的标准(与 Sync 需要从多个线程安全并发修改的更难的标准相比).

As a result, you would generally expect any Sync struct to be Send too, because Send is such an easy bar to reach (compared to the much harder bar of being Sync which requires safe concurrent modification from multiple threads).

但是,没有什么可以阻止类型的创建者将其明确标记为 not Send.例如,让我们复苏条件!

However, nothing prevents the creator of a type to specifically mark it as not Send. For example, let's resuscitate conditions!

在 Lisp 中,条件的想法是你为给定的条件设置一个处理程序(比如:FileNotFound),然后当在堆栈深处时满足这个条件,然后你的处理程序被调用.

The idea of conditions, in Lisp, is that you setup a handler for a given condition (say: FileNotFound) and then when deep in the stack this condition is met then your handler is called.

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

How would you implement this in Rust?

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

Well, to preserve threads independence, you would use thread-local storage for the condition handlers (see std::thread_local!). Each condition would be a stack of condition handlers, with either only the top one invoked or an iterative process starting from the top one but reaching down until one succeeds.

但是,您将如何设置它们?

But then, how would you set them?

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

Personally, I'd use RAII! I would bind the condition handler in the thread-local stack and register it in the frame (for example, using an intrusive doubly-linked list as the stack).

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

This way, when I am done, the condition handler automatically un-registers itself.

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

Of course, the system has to account for users doing unexpected things (like storing the condition handlers in the heap and not dropping them in the order they were created), and this is why we use a doubly-linked list, so that the handler can un-register itself from the middle of the stack if necessary.

所以我们有一个:

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

并且真正的"处理程序由用户作为 T 传递.

and the "real" handler is passed by the user as T.

这个处理程序是 Sync 吗?

Would this handler be Sync?

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

Possibly, depends how you create it but there is no reason you could not create a handler so that a reference to it could not be shared between multiple threads.

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

Note: those threads could not access its prev/next data members, which are private, and need not be Sync.

这个处理程序会是Send吗?

除非特别小心,否则不会.

Unless specific care is taken, no.

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

The prev and next fields are not protected against concurrent accesses, and even worse if the handler were to be dropped while another thread had obtained a reference to it (for example, another handler trying to un-register itself) then this now dangling reference would cause Undefined Behavior.

注意:后一个问题意味着只是将 Option<*mut Handler> 切换为 AtomicPtr> 不是充足的;请参阅编写无锁算法的常见陷阱更多详情.

Note: the latter issue means that just switching Option<*mut Handler<T>> for AtomicPtr<ConditionHandler<T>> is not sufficient; see Common Pitfalls in Writing Lock-Free Algorithms for more details.

你就知道了:ConditionHandlerSync 如果 TSync 但会永远不要发送(按原样).

And there you have it: a ConditionHandler<T> is Sync if T is Sync but will never be Send (as is).

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

For completeness, many types implement Send but not Sync (most Send types, actually): Option or Vec for example.

这篇关于仅实现 Send 和 Sync 之一的类型示例有哪些?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆