【发布时间】:2021-05-21 13:43:52
【问题描述】:
在 rust 中,有 AtomicBool 这样的东西。定义为:
可以在线程之间安全共享的布尔类型。
我了解,如果您使用布尔值来实现线程锁,以便从多个线程中使用来控制对资源的访问,请执行以下操作:
// Acquire the lock
if thread_lock == false:
thread_lock = true
...
// Release the lock
thread_lock = false
绝对不是线程安全的。两个线程可以同时读取thread_lock变量,看到它是解锁的(false),设置为true,都认为自己拥有线程的独占访问权限。
使用适当的线程锁,您需要一个布尔值,当您尝试设置它时,会发生以下两种情况之一:
- 如果另一个线程已经拥有锁,则尝试获取锁可能会失败
- 尝试获取锁将阻塞,直到没有其他线程拥有锁
我不知道 Rust 是否有这样的概念,但我知道 Python 的 threading.Lock 正是这样做的。
据我所知,这不是AtomicBool 所针对的场景。 AtomicBool 具有 load() 方法和 store() 方法。既不返回 Result<bool> 类型(暗示操作不会失败),据我所知,也没有任何类型的阻塞。
AtomicBool 究竟能保护我们免受什么影响?为什么我们不能使用来自不同线程的常规布尔值(除了编译器不允许我们这样做)?
我唯一能想到的是,当一个线程将位写入内存时,另一个线程可能会尝试同时读取这些位。布尔值是 8 位。如果在另一个线程尝试读取数据时写入了 8 位中的 4 位,则读取的数据将是旧值的 4 位和新值的 4 位。这是正在解决的问题吗?这会发生吗?即使在这种情况下,bool 似乎也不需要是原子的,因为在 8 位中,只有一位很重要,即 0 或 1。
【问题讨论】:
-
线程锁有
Mutex和RwLock。 -
您也可以使用
atomic_bool.compare_and_swap(false, true, SeqCst),它将布尔值设置为true,并且只有在原始值为false时才返回false。这可以用来实现锁,但是当你可以只使用Mutex<()>时就没有必要了。 -
这不是关于访问布尔位的竞赛,而是关于其他内存访问。内存并发比较复杂,不过可以看cfsamsonbooks.gitbook.io/explaining-atomics-in-rust
WTF?/AHA! < 1的介绍。 -
你是否能想到一些可能出错的方法是无关紧要的。适用的规则要么保证它是安全的,要么不保证它是安全的。事情可能会以没人能想到的方式失败,并且存在规则和标准,因此我们不必尝试考虑可能失败的所有可能方式。
-
AtomicBool 究竟能保护我们免受什么影响? - 简而言之,防止编译器和 CPU 对优化单线程程序但破坏多线程程序的指令重新排序。有关编译器重新排序的示例,请参见 this article,对于基于 CPU 的示例,请参见 this 和 this。 (由于外部链接太多,未发布作为答案。)
标签: multithreading rust