Але*_*ков 8 concurrency double-checked-locking rust
我发现了这篇文章,但它看起来不对,因为Cell它不能保证set()锁定和锁定之间的同步get().
是否Atomic_.store(true, Ordering::Release)影响其他非原子写操作?
我试着写它AtomicPtr看起来接近Java风格,但它失败了.AtomicPtr在这种情况下,我找不到正确使用的例子.
Mat*_* M. 12
是否
Atomic_.store(true, Ordering::Release)影响其他非原子写操作?
是.
实际上,Ordering存在的主要原因是对非原子读写强加一些排序保证:
轻松
约束越少Ordering; 唯一不能重新排序的操作是对相同原子值的操作:
atomic.set(4, Ordering::Relaxed);
other = 8;
println!("{}", atomic.get(Ordering::Relaxed));
Run Code Online (Sandbox Code Playgroud)
保证打印4.如果另一个线程读取atomic是4,它不知道是否保证other是8或不是.
发布/采集
写和读障碍分别为:
store操作一起使用,并保证执行先前的写入,load操作一起使用,并保证进一步读取将看到至少与对应之前写入的值一样新的值store.所以:
// thread 1
one = 1;
atomic.set(true, Ordering::Release);
two = 2;
// thread 2
while !atomic.get(Ordering::Acquire) {}
println!("{} {}", one, two);
Run Code Online (Sandbox Code Playgroud)
保证即one是1,并且没有任何说明two.
请注意,Relaxed带有Acquire负载的Release商店或带有负载的商店Relaxed基本上没有意义.
请注意,Rust提供AcqRel:它的行为与Release商店和Acquire加载相同,因此您不必记住哪个是...我不推荐它,因为提供的保证是如此不同.
SeqCst
最受约束的Ordering.保证一次性跨所有线程排序.
在Rust中编写双重检查锁定的正确方法是什么?
因此,双重检查锁定是利用这些原子操作来避免在不必要时锁定.
想法是有3件:
并使用它们:
困难在于确保非原子读/写正确排序(并以正确的顺序显示).从理论上讲,你需要完全围栏; 在实践中遵循C11/C++ 11内存模型的习惯用法就足够了,因为编译器必须使其工作.
我们先来看一下代码(简化):
struct Lazy<T> {
initialized: AtomicBool,
lock: Mutex<()>,
value: UnsafeCell<Option<T>>,
}
impl<T> Lazy<T> {
pub fn get_or_create<'a, F>(&'a self, f: F) -> &'a T
where
F: FnOnce() -> T
{
if !self.initialized.load(Ordering::Acquire) { // (1)
let _lock = self.lock.lock().unwrap();
if !self.initialized.load(Ordering::Relaxed) { // (2)
let value = unsafe { &mut *self.value.get() };
*value = Some(f(value));
self.initialized.store(true, Ordering::Release); // (3)
}
}
unsafe { &*self.value.get() }.as_ref().unwrap()
}
}
Run Code Online (Sandbox Code Playgroud)
有3个原子操作,通过注释编号.我们现在可以检查内存排序的哪种保证,每个必须提供正确性.
(1)如果为true,则返回对该值的引用,该引用必须引用有效内存.这要求在原子变为真之前执行对该存储器的写入,并且只有在该存储器为真之后才执行该存储器的读取.因此(1)要求Acquire和(3)要求Release.
另一方面,(2)没有这样的约束,因为锁定a Mutex相当于一个完整的内存屏障:所有写入都保证在之前发生,所有读取只发生在之后.因此,此负载无需进一步保证,因此Relaxed是最优化的.
因此,就我而言,这种双重检查的实施在实践中看起来是正确的.
为了进一步阅读,我真的推荐Preshing的文章,它与您链接的文章相关联.它显着突出了理论(围栏)和实践(原子载荷/商店降低到围栏)之间的差异.