我有一个包含一个初始化相当昂贵的字段的结构,所以我希望能够懒得这样做。但是,在采用&self
的方法中,这可能是必要的。该字段还需要能够在初始化后进行修改,但这只会在采用&mut self
的方法中进行。
在Rust中执行此操作的正确方法(如惯用语和线程安全方式)是什么?在我看来,这两个约束中的任何一个都是微不足道的:
lazy-init
的Lazy<T>
类型。但是,我不太清楚如何处理两者。 RwLock
似乎是相关的,但看起来在lazy-init
的源代码中我看到了线程安全的延迟初始化是相当棘手的,所以我对基于它推出自己的解决方案犹豫不决
答案 0 :(得分:3)
最简单的解决方案是RwLock<Option<T>>
。
但是,我不太清楚如何处理两者。
RwLock
似乎是相关的,但看起来在lazy-init
的源代码中我看到了线程安全的延迟初始化是相当棘手的,所以我对根据它推出自己的解决方案犹豫不决
lazy-init
使用棘手的代码,因为它保证了创建后的无锁访问。无锁总是有点棘手。
请注意,在Rust中很容易判断某些内容是否棘手:棘手意味着使用unsafe
块。由于您可以使用RwLock<Option<T>>
而没有任何不安全的阻止,因此您无需担心。
如果要捕获初始化一次的闭包,可能需要RwLock<Option<T>>
的变体,而不是必须在每个潜在的初始化调用站点传递它。
在这种情况下,您需要RwLock<SimpleLazy<T>>
之类的地方:
enum SimpleLazy<T> {
Initialized(T),
Uninitialized(Box<FnOnce() -> T>),
}
您无需担心SimpleLazy<T>
Sync
,因为RwLock
会照顾您。{/ p>