文件说
\n\n\n返回对基础数据的可变引用。\n由于此调用可变地借用互斥体,因此不需要进行实际锁定\xe2\x80\x93 可变借用静态地保证不存在锁。
\n
所以问题是不需要锁定。当然,如果互斥体(in)没有直接从任何不安全块中使用,那么任何线程都不可能持有对其的引用,因此无法使用它。这也意味着,为了编译 get_mut 的调用,如果任何线程正在使用它,则该线程必须已经完成其执行。任何新线程都可以访问受互斥锁保护的数据,因为它将像获取语义一样从内存中读取,因此通过 get_mut 对数据所做的任何更改都将对任何新线程可见。
\n但是,如果从不安全的块中使用互斥体,则某些线程(可能像我的例子中的 ffi 一样)可能仍然在互斥体上有一个指针,并且可以保持锁定并使用数据,或者只是完成数据的变异并解锁互斥体。在前一种情况下,显然是UB,在后一种情况下,这是一个竞争条件,这也是UB,因为调用get_mut的线程可能看不到受保护数据的最新状态,该状态刚刚由另一个线程,它通过指针访问互斥体。为了使最新的更改在调用 get_mut 的线程上可见,应该保留获取/释放语义,但 get_mut 不会调用任何获取操作。
\nget_mut 是一个有用的函数,但我不相信它是线程安全的,因此应该是不安全的。
\nRust 中可变引用的主要属性是它们是唯一的。也就是说,当代码作为一个整体是健全的时,可以保证访问可变引用所引用的值的唯一方法是通过该确切的引用。在安全代码中,这是自动强制执行的。在不安全的代码中,包括 FFI,这是您(作为编写者unsafe)应该维护的不变量。
特别是,当您拥有对 的可变引用时Mutex,让任何其他地方访问相同的互斥体或其背后的数据是明确且立即的 UB。特别是,让其他人锁定它本质上是 UB,因为根据定义,解锁将访问互斥锁(以存储“未锁定”位)。
因此,如果某些unsafe代码导致get_mut非线程安全,那么该不安全代码本身就是不健全的。
| 归档时间: |
|
| 查看次数: |
278 次 |
| 最近记录: |