在Rust Atomics and Locks中,建议使用以下代码来适当地实现简化的Arc
的drop
特性:(代码是我的)
unsafe {
if 1 == (*self.inner).strong.fetch_sub(1, Release) {
fence(Acquire);
let box_ = Box::rom_raw(self.inner);
drop(box_);
}
}
其中(*self.inner).strong
是AtomicUsize
.
所以我的问题是:
我理解acquire
将与前一个release
(与写入加载值的线程)建立"happens-before/synchronize-with"关系.为了正确地drop
值,我们需要每个Arc
都有他们的fetch_sub
一个接一个地链接.
我不明白这里怎么能保证这一点.我可以理解,如果我们在一次操作中完成acquired
个原子值,减go 1,然后是release
d(基本上是fetch_sub
次排序或一个比较和交换循环).
在这里,我们只有在加载1的时候才"获取".我对fetch_sub
使用Release
的理解是fetch
部分是relaxed
.基于这种理解,我对上述代码有两个问题:
1
这个案子是不是有可能:
Thread A:
load: 2. (t = 1)
write 1 (t = ?)
Thread B:
load: 2. (t = 1)
write 1 (t = ?)
因此价值从未下降?我看不出load
如何保证它对值具有独占访问权,这意味着它将始终按顺序加载.
2.
我难道不是在1
的读数和下降之间建立了一种"之前发生"的关系吗?我认为这很好,因为如果我真的看到1
,我可以下降only,但如何保证我看到1
,而不会在原子上进行数据竞赛?
我怀疑我的误解来自于原子/排序提供的保证,但是