Skip to content

Commit

Permalink
Resolve mutex translation issue #100 (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
fwqaaq authored May 30, 2024
1 parent eef4f7d commit acb38de
Showing 1 changed file with 5 additions and 5 deletions.
10 changes: 5 additions & 5 deletions 1_Basic_of_Rust_Concurrency.md
Original file line number Diff line number Diff line change
Expand Up @@ -617,17 +617,17 @@ note: required by a bound in `spawn`

在线程之间共享(可变)数据更常规的有用工具是 `mutex`,它是“互斥”(mutual exclusion)的缩写。mutex 的工作是通过暂时阻塞其它试图同时访问某些数据的线程,来确保线程对某些数据进行独占访问。

概念上,mutex 仅有两个状态:锁定和解锁。当线程锁定一个未解锁的 mutex,mutex 被标记为锁定,线程可以立即继续。当线程尝试锁定一个已上锁的 mutex,操作将*阻塞*。当线程等待 mutex 解锁时,其会置入睡眠状态。解锁仅能在锁定的 mutex 上进行,并且应当由锁定它的同一线程完成。如果其它线程正在等待锁定 mutex,解锁将导致唤醒其中一个线程,因此它可以尝试再次锁定 mutex 并且继续它的过程
概念上,mutex 仅有两个状态:解锁和锁定。当线程锁定一个未上锁的 mutex,mutex 被标记为锁定,线程可以立即继续。当线程尝试锁定一个已上锁的 mutex,操作将*阻塞*。当线程等待 mutex 解锁时,其会置入睡眠状态。解锁操作仅能在已上锁的 mutex 上进行,并且应当由锁定它的同一线程完成。如果其它线程正在等待锁定 mutex,解锁将导致唤醒其中一个线程,因此它可以尝试再次锁定 mutex 并且继续它的进程

使用 mutex 保护数据仅是所有线程之间的约定,当它们持有 mutex 锁定时,它们才能获取数据。这种方式,没有两个线程可以并发地获取数据和导致数据竞争。
使用 mutex 保护数据仅是所有线程之间的约定,当它们持有 mutex 锁时,它们才能获取数据。这种方式,没有两个线程可以并发地获取数据和导致数据竞争。

### Rust 的互斥锁

(<a href="https://marabos.nl/atomics/basics.html#rusts-mutex" target="_blank">英文版本</a>)

Rust 的标准库通过 `std::sync::Mutex<T>` 提供这个功能。它对类型 T 进行范型化,该类型 T 是 mutex 所保护的数据类型。通过将 T 作为 mutex 的一部分,该数据仅可以通过 mutex 获取,从而提供一个安全的接口,以保证所有线程都遵守这个约定。

为确保锁定的 mutex 仅通过锁定它的线程解锁,所以它没有 `unlock()` 方法。然而,它的 `lock()` 方法返回一个称为 `MutexGuard` 的特殊类型。该 guard 表示保证我们已经锁定 mutex。它通过 `DerefMut` trait 行为表现像一个独占引用,使我们能够独占访问互斥体保护的数据。解锁 mutex 通过丢弃 guard 完成。当我们丢弃 guard 时,我们我们放弃了获取数据的能力,并且 guard 的 `Drop` 实现将解锁 mutex。
为确保已上锁的 mutex 仅通过锁定它的线程解锁,所以它没有 `unlock()` 方法。然而,它的 `lock()` 方法返回一个称为 `MutexGuard` 的特殊类型。该 guard 表示保证我们已经锁定 mutex。它通过 `DerefMut` trait 行为表现像一个独占引用,使我们能够独占访问互斥体保护的数据。解锁 mutex 通过丢弃 guard 完成。当我们丢弃 guard 时,我们我们放弃了获取数据的能力,并且 guard 的 `Drop` 实现将解锁 mutex。

让我们看一个示例,实践中的 mutex:

Expand Down Expand Up @@ -761,9 +761,9 @@ Rust 标准库通过 `std::sync::RwLock<T>` 类型提供该锁。它与标准库

它实际上是 `RefCell` 的多线程版本,动态地跟踪引用的数量以确保借用规则得到维护。

`Mutex<T>``RwLock<T>` 都需要 T 是 Send,因为它们可能发送 T 到另一个线程。除此之外,`RwLock<T>` 也需要 T 实现 Sync,因为它允许多个线程对受保护的数据持有共享引用(`&T`)。(严格地说,你可以创建一个并没有实现这些需求 T 的锁定,但是你不能在线程之间共享它,因为锁本身并没有实现 Sync)。
`Mutex<T>``RwLock<T>` 都需要 T 是 Send,因为它们可能发送 T 到另一个线程。除此之外,`RwLock<T>` 也需要 T 实现 Sync,因为它允许多个线程对受保护的数据持有共享引用(`&T`)。(严格地说,你可以创建一个并没有实现这些需求 T 的锁,但是你不能在线程之间共享它,因为锁本身并没有实现 Sync)。

Rust 标准库仅提供一种通用的 `RwLock` 类型,但它的实现依赖于操作系统。读写锁之间有很多细微差别。当有 writer 等待时,即使当锁已经读取锁定时,很多实现将阻塞新的 reader。这样做是为了防止 *writer 挨饿*,在这种情况下,很多 reader 将共同持有锁而导致锁从不解锁,从而不允许任何 writer 更新数据。
Rust 标准库仅提供一种通用的 `RwLock` 类型,但它的实现依赖于操作系统。读写锁之间有很多细微差别。当有 writer 等待时,即使当锁已经读锁定的,很多实现将阻塞新的 reader。这样做是为了防止 *writer 挨饿*,在这种情况下,很多 reader 将集体阻止锁解锁,从而不允许任何 writer 更新数据。

<div class="box">
<h2 style="text-align: center;">在其他语言中的互斥锁</h2>
Expand Down

0 comments on commit acb38de

Please sign in to comment.