在 Rust 中拥有线程安全的延迟初始化的可能可变值的正确方法是什么?
What's the right way to have a thread-safe lazy-initialized possibly mutable value in Rust?
我有一个结构,其中包含一个初始化起来相当昂贵的字段,所以我希望能够懒惰地这样做。但是,这在采用 &self
的方法中可能是必需的。该字段还需要能够在初始化后进行修改,但这只会发生在采用 &mut self
的方法中。
在 Rust 中正确的(如惯用的,以及线程安全的)方法是什么?在我看来,这两个约束中的任何一个都是微不足道的:
- 如果它只需要延迟初始化,而不是变异,我可以简单地使用
lazy-init
的 Lazy<T>
类型。
- 如果它只需要可变而不是懒惰,那么我可以只使用普通字段(显然)。
但是,我不太确定如何处理这两个位置。 RwLock
似乎是相关的,但鉴于我对 lazy-init
的源代码的了解,线程安全的惰性初始化似乎存在相当大的技巧,因此我对基于它推出自己的解决方案犹豫不决.
最简单的解决方案是RwLock<Option<T>>
。
However, I'm not quite sure what to do with both in place. RwLock
seems relevant, but it appears that there is considerable trickiness to thread-safe lazy initialization given what I've seen of lazy-init
's source, so I am hesitant to roll my own solution based on it.
lazy-init
使用棘手的代码,因为它保证 lock-free 创建后的访问。 Lock-free 总是有点棘手。
请注意,在 Rust 中很容易判断某事是否棘手:棘手意味着使用 unsafe
块。由于您可以在没有任何不安全块的情况下使用 RwLock<Option<T>>
,因此您无需担心。
如果您想捕获一个用于初始化的闭包一次,而不是必须在每次可能的初始化时传递它[=40],则可能需要 RwLock<Option<T>>
的变体=].
在这种情况下,您需要类似 RwLock<SimpleLazy<T>>
的内容,其中:
enum SimpleLazy<T> {
Initialized(T),
Uninitialized(Box<FnOnce() -> T>),
}
您不必担心制作 SimpleLazy<T>
Sync
,因为 RwLock
会为您处理。
我有一个结构,其中包含一个初始化起来相当昂贵的字段,所以我希望能够懒惰地这样做。但是,这在采用 &self
的方法中可能是必需的。该字段还需要能够在初始化后进行修改,但这只会发生在采用 &mut self
的方法中。
在 Rust 中正确的(如惯用的,以及线程安全的)方法是什么?在我看来,这两个约束中的任何一个都是微不足道的:
- 如果它只需要延迟初始化,而不是变异,我可以简单地使用
lazy-init
的Lazy<T>
类型。 - 如果它只需要可变而不是懒惰,那么我可以只使用普通字段(显然)。
但是,我不太确定如何处理这两个位置。 RwLock
似乎是相关的,但鉴于我对 lazy-init
的源代码的了解,线程安全的惰性初始化似乎存在相当大的技巧,因此我对基于它推出自己的解决方案犹豫不决.
最简单的解决方案是RwLock<Option<T>>
。
However, I'm not quite sure what to do with both in place.
RwLock
seems relevant, but it appears that there is considerable trickiness to thread-safe lazy initialization given what I've seen oflazy-init
's source, so I am hesitant to roll my own solution based on it.
lazy-init
使用棘手的代码,因为它保证 lock-free 创建后的访问。 Lock-free 总是有点棘手。
请注意,在 Rust 中很容易判断某事是否棘手:棘手意味着使用 unsafe
块。由于您可以在没有任何不安全块的情况下使用 RwLock<Option<T>>
,因此您无需担心。
如果您想捕获一个用于初始化的闭包一次,而不是必须在每次可能的初始化时传递它[=40],则可能需要 RwLock<Option<T>>
的变体=].
在这种情况下,您需要类似 RwLock<SimpleLazy<T>>
的内容,其中:
enum SimpleLazy<T> {
Initialized(T),
Uninitialized(Box<FnOnce() -> T>),
}
您不必担心制作 SimpleLazy<T>
Sync
,因为 RwLock
会为您处理。