1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-03-18 05:37:52 +02:00

zh-CN: Translate Concurrency morning (#785)

* zh-CN: translate the Concurrency morning

* Apply suggestions from code review

Co-authored-by: Anlun Xu <anlunx@google.com>
Co-authored-by: Siwei Xu <xusiwei1236@gmail.com>

* Apply suggestions from code review

Co-authored-by: Anlun Xu <anlunx@google.com>
Co-authored-by: wnghl <wnghilin@gmail.com>

---------

Co-authored-by: Anlun Xu <anlunx@google.com>
Co-authored-by: Siwei Xu <xusiwei1236@gmail.com>
Co-authored-by: wnghl <wnghilin@gmail.com>
This commit is contained in:
Martin Geisler 2023-06-14 05:06:59 +02:00 committed by GitHub
parent c878ecd7a8
commit 02dea6bd28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1223,7 +1223,7 @@ msgstr ""
#: src/exercises/concurrency/afternoon.md:11
#: src/exercises/concurrency/dining-philosophers-async.md:75
msgid "<details>"
msgstr ""
msgstr "<details>"
#: src/welcome.md:52
msgid ""
@ -1330,7 +1330,7 @@ msgstr ""
#: src/exercises/concurrency/afternoon.md:17
#: src/exercises/concurrency/dining-philosophers-async.md:79
msgid "</details>"
msgstr ""
msgstr "</details>"
#: src/running-the-course.md:1
msgid "# Running the Course"
@ -5669,7 +5669,7 @@ msgstr ""
#: src/methods/example.md:1 src/concurrency/shared_state/example.md:1
msgid "# Example"
msgstr ""
msgstr "# 示例"
#: src/methods/example.md:3
msgid ""
@ -14510,13 +14510,14 @@ msgstr ""
#: src/concurrency.md:1
msgid "# Welcome to Concurrency in Rust"
msgstr ""
msgstr "# 欢迎了解 Rust 中的并发"
#: src/concurrency.md:3
msgid ""
"Rust has full support for concurrency using OS threads with mutexes and\n"
"channels."
msgstr ""
"Rust 完全支持使用带有互斥锁和通道的操作系统线程进行并发。"
#: src/concurrency.md:6
msgid ""
@ -14526,14 +14527,17 @@ msgid ""
"you\n"
"can rely on the compiler to ensure correctness at runtime."
msgstr ""
"Rust 类型系统能帮助我们把许多并发bug转换为编译期bug\n"
"发挥着重要作用。这通常称为“无畏并发”,因为你可以依靠编译器来确保\n"
"运行时的正确性。"
#: src/concurrency/threads.md:1
msgid "# Threads"
msgstr ""
msgstr "# 线程"
#: src/concurrency/threads.md:3
msgid "Rust threads work similarly to threads in other languages:"
msgstr ""
msgstr "Rust 线程的运作方式与其他语言中的线程类似:"
#: src/concurrency/threads.md:5
msgid ""
@ -14556,6 +14560,24 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable\n"
"use std::thread;\n"
"use std::time::Duration;\n"
"\n"
"fn main() {\n"
" thread::spawn(|| {\n"
" for i in 1..10 {\n"
" println!(\"Count in thread: {i}!\");\n"
" thread::sleep(Duration::from_millis(5));\n"
" }\n"
" });\n"
"\n"
" for i in 1..5 {\n"
" println!(\"Main thread: {i}\");\n"
" thread::sleep(Duration::from_millis(5));\n"
" }\n"
"}\n"
"```"
#: src/concurrency/threads.md:24
msgid ""
@ -14563,6 +14585,9 @@ msgid ""
"* Thread panics are independent of each other.\n"
" * Panics can carry a payload, which can be unpacked with `downcast_ref`."
msgstr ""
"* 线程均为守护程序线程,主线程不会等待这些线程。\n"
"* 线程紧急警报 (panic) 是彼此独立的。\n"
"* 紧急警报可以携带载荷,并可以使用 `downcast_ref` 对载荷进行解压缩。"
#: src/concurrency/threads.md:32
msgid ""
@ -14580,14 +14605,24 @@ msgid ""
"panic\n"
" payload. This is a good time to talk about [`Any`]."
msgstr ""
"* 请注意,线程在达到 10 之前就停止了,而主线程并\n"
"没有等待。\n"
"\n"
"* 使用 `let handle = thread::spawn(...)` 和后面的 `handle.join()` 等待\n"
"线程完成。\n"
"\n"
"* 在线程中触发紧急警报,并注意这为何不会影响到 `main`。\n"
"\n"
"* 使用 `handle.join()` 的 `Result` 返回值来获取对紧急警报\n"
"载荷的访问权限。现在有必要介绍一下 [`Any`] 了。"
#: src/concurrency/scoped-threads.md:1
msgid "# Scoped Threads"
msgstr ""
msgstr "# 范围线程"
#: src/concurrency/scoped-threads.md:3
msgid "Normal threads cannot borrow from their environment:"
msgstr ""
msgstr "常规线程不能从它们所处的环境中借用:"
#: src/concurrency/scoped-threads.md:5
msgid ""
@ -14603,10 +14638,21 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable,compile_fail\n"
"use std::thread;\n"
"\n"
"fn main() {\n"
" let s = String::from(\"Hello\");\n"
"\n"
" thread::spawn(|| {\n"
" println!(\"Length: {}\", s.len());\n"
" });\n"
"}\n"
"```"
#: src/concurrency/scoped-threads.md:17
msgid "However, you can use a [scoped thread][1] for this:"
msgstr ""
msgstr "不过,你可以使用[范围线程][1]来实现此目的:"
#: src/concurrency/scoped-threads.md:19
msgid ""
@ -14624,6 +14670,19 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable\n"
"use std::thread;\n"
"\n"
"fn main() {\n"
" let s = String::from(\"Hello\");\n"
"\n"
" thread::scope(|scope| {\n"
" scope.spawn(|| {\n"
" println!(\"Length: {}\", s.len());\n"
" });\n"
" });\n"
"}\n"
"```"
#: src/concurrency/scoped-threads.md:37
msgid ""
@ -14634,10 +14693,15 @@ msgid ""
"thread, or immutably by any number of threads.\n"
" "
msgstr ""
"* 其原因在于,在 `thread::scope` 函数完成后,可保证所有线程都已联结在一起,使"
"得线程能够返回借用的数据。\n"
"* 此时须遵守常规 Rust 借用规则:你可以通过一个线程以可变的方式借用,也可以通"
"过任意数量的线程以不可变的方式借用。\n"
" "
#: src/concurrency/channels.md:1
msgid "# Channels"
msgstr ""
msgstr "# 通道"
#: src/concurrency/channels.md:3
msgid ""
@ -14645,6 +14709,8 @@ msgid ""
"parts\n"
"are connected via the channel, but you only see the end-points."
msgstr ""
"Rust 通道(Channel)包含两个部分:`Sender<T>` 和 `Receiver<T>`。这两个部分\n"
"通过通道进行连接,但你只能看到端点。"
#: src/concurrency/channels.md:6
msgid ""
@ -14667,6 +14733,24 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable\n"
"use std::sync::mpsc;\n"
"use std::thread;\n"
"\n"
"fn main() {\n"
" let (tx, rx) = mpsc::channel();\n"
"\n"
" tx.send(10).unwrap();\n"
" tx.send(20).unwrap();\n"
"\n"
" println!(\"Received: {:?}\", rx.recv());\n"
" println!(\"Received: {:?}\", rx.recv());\n"
"\n"
" let tx2 = tx.clone();\n"
" tx2.send(30).unwrap();\n"
" println!(\"Received: {:?}\", rx.recv());\n"
"}\n"
"```"
#: src/concurrency/channels.md:27
msgid ""
@ -14677,14 +14761,20 @@ msgid ""
"counterpart `Sender` or\n"
" `Receiver` is dropped and the channel is closed."
msgstr ""
"* `mpsc` 代表多个生产方,单个使用方。`Sender` 和 `SyncSender` 会实现 `Clone`"
"(因此,\n"
"你可以设置多个生产方),但 `Receiver` 不会实现。\n"
"* `send()` 和 `recv()` 会返回 `Result`。如果它们返回 `Err`,则表示对应的 "
"`Sender` 或 `Receiver`\n"
"已被丢弃,且通道已关闭。"
#: src/concurrency/channels/unbounded.md:1
msgid "# Unbounded Channels"
msgstr ""
msgstr "# 无界通道"
#: src/concurrency/channels/unbounded.md:3
msgid "You get an unbounded and asynchronous channel with `mpsc::channel()`:"
msgstr ""
msgstr "你可以使用 `mpsc::channel()` 获得无边界的异步通道:"
#: src/concurrency/channels/unbounded.md:5
msgid ""
@ -14712,14 +14802,37 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable\n"
"use std::sync::mpsc;\n"
"use std::thread;\n"
"use std::time::Duration;\n"
"\n"
"fn main() {\n"
" let (tx, rx) = mpsc::channel();\n"
"\n"
" thread::spawn(move || {\n"
" let thread_id = thread::current().id();\n"
" for i in 1..10 {\n"
" tx.send(format!(\"Message {i}\")).unwrap();\n"
" println!(\"{thread_id:?}: sent Message {i}\");\n"
" }\n"
" println!(\"{thread_id:?}: done\");\n"
" });\n"
" thread::sleep(Duration::from_millis(100));\n"
"\n"
" for msg in rx.iter() {\n"
" println!(\"Main: got {msg}\");\n"
" }\n"
"}\n"
"```"
#: src/concurrency/channels/bounded.md:1
msgid "# Bounded Channels"
msgstr ""
msgstr "# 有界通道"
#: src/concurrency/channels/bounded.md:3
msgid "Bounded and synchronous channels make `send` block the current thread:"
msgstr ""
msgstr "有边界的同步通道会使 `send` 阻塞当前线程:"
#: src/concurrency/channels/bounded.md:5
msgid ""
@ -14747,16 +14860,39 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable\n"
"use std::sync::mpsc;\n"
"use std::thread;\n"
"use std::time::Duration;\n"
"\n"
"fn main() {\n"
" let (tx, rx) = mpsc::sync_channel(3);\n"
"\n"
" thread::spawn(move || {\n"
" let thread_id = thread::current().id();\n"
" for i in 1..10 {\n"
" tx.send(format!(\"Message {i}\")).unwrap();\n"
" println!(\"{thread_id:?}: sent Message {i}\");\n"
" }\n"
" println!(\"{thread_id:?}: done\");\n"
" });\n"
" thread::sleep(Duration::from_millis(100));\n"
"\n"
" for msg in rx.iter() {\n"
" println!(\"Main: got {msg}\");\n"
" }\n"
"}\n"
"```"
#: src/concurrency/send-sync.md:1
msgid "# `Send` and `Sync`"
msgstr ""
msgstr "# `Send` 和 `Sync`"
#: src/concurrency/send-sync.md:3
msgid ""
"How does Rust know to forbid shared access across thread? The answer is in "
"two traits:"
msgstr ""
msgstr "Rust 如何知道要禁止跨线程共享访问?答案在于 Rust 的两个特征:"
#: src/concurrency/send-sync.md:5
msgid ""
@ -14767,6 +14903,10 @@ msgid ""
"thread\n"
" boundary."
msgstr ""
"* [`Send`][1]:如果跨线程边界移动 `T` 是安全的,则类型 `T`\n"
"为 `Send`。\n"
"* [`Sync`][2]:如果跨线程边界移动 `&T` 是安全的,则类型 `T`\n"
"为 `Sync`。"
#: src/concurrency/send-sync.md:10
msgid ""
@ -14776,6 +14916,10 @@ msgid ""
"them manually when you\n"
"know it is valid."
msgstr ""
"`Send` 和 `Sync` 均为[不安全特征][3]。只要类型仅包含 `Send` 和 `Sync` 类型,"
"编译器就会自动为类型派生\n"
"这两种特征。你也可以手动实现它们(如果你确定这样\n"
"有效的话)。"
#: src/concurrency/send-sync.md:20
msgid ""
@ -14784,16 +14928,19 @@ msgid ""
"* They can be used in the generic constraints as normal traits.\n"
" "
msgstr ""
"* 不妨将这些特征视为类型包含某些线程安全属性的标记。\n"
"* 它们可以在泛型约束中作为常规特征使用。\n"
" "
#: src/concurrency/send-sync/send.md:1
msgid "# `Send`"
msgstr ""
msgstr "# `Send`"
#: src/concurrency/send-sync/send.md:3
msgid ""
"> A type `T` is [`Send`][1] if it is safe to move a `T` value to another "
"thread."
msgstr ""
msgstr "> 如果将 `T` 值移动到另一个线程是安全的,则类型 `T` 为 [`Send`][1]。"
#: src/concurrency/send-sync/send.md:5
msgid ""
@ -14803,6 +14950,9 @@ msgid ""
"thread\n"
"and deallocate it in another."
msgstr ""
"将所有权转移到另一个线程的影响是,“析构函数”将在相应线程中\n"
"运行。因此,问题在于你何时可以在一个线程中分配某个值,然后在\n"
"另一个线程中取消分配该值。"
#: src/concurrency/send-sync/send.md:13
msgid ""
@ -14810,10 +14960,12 @@ msgid ""
"a\n"
"single thread."
msgstr ""
"例如,与 SQLite 库的连接只能通过\n"
"单个线程访问。"
#: src/concurrency/send-sync/sync.md:1
msgid "# `Sync`"
msgstr ""
msgstr "# `Sync`"
#: src/concurrency/send-sync/sync.md:3
msgid ""
@ -14821,14 +14973,16 @@ msgid ""
"multiple\n"
"> threads at the same time."
msgstr ""
"> 如果同时从多个线程访问 `T` 值是安全的,则类型 `T`\n"
">为 [`Sync`][1]。"
#: src/concurrency/send-sync/sync.md:6
msgid "More precisely, the definition is:"
msgstr ""
msgstr "更准确地说,定义是:"
#: src/concurrency/send-sync/sync.md:8
msgid "> `T` is `Sync` if and only if `&T` is `Send`"
msgstr ""
msgstr "> 当且仅当 `&T` 为 `Send` 时,`T` 为 `Sync`"
#: src/concurrency/send-sync/sync.md:14
msgid ""
@ -14836,6 +14990,8 @@ msgid ""
"thread-safe for shared use, it is also thread-safe to pass references of it "
"across threads."
msgstr ""
"该语句实质上是一种简写形式,表示如果某个类型对于共享使用是线程安全的,那么跨"
"线程传递对该类型的引用也是线程安全的。"
#: src/concurrency/send-sync/sync.md:16
msgid ""
@ -14845,18 +15001,21 @@ msgid ""
"is also safe to move to another thread, because the data it references can "
"be accessed from any thread safely."
msgstr ""
"这是因为如果某个类型为 Sync,则意味着它可以在多个线程之间共享,而不存在数据争"
"用或其他同步问题的风险,因此将其移动到另一个线程是安全的。对该类型的引用同样"
"可以安全地移动到另一个线程,因为它引用的数据可以从任何线程安全地访问。"
#: src/concurrency/send-sync/examples.md:1
msgid "# Examples"
msgstr ""
msgstr "# 示例"
#: src/concurrency/send-sync/examples.md:3
msgid "## `Send + Sync`"
msgstr ""
msgstr "## `Send + Sync`"
#: src/concurrency/send-sync/examples.md:5
msgid "Most types you come across are `Send + Sync`:"
msgstr ""
msgstr "你遇到的类型大都属于 `Send + Sync`:"
#: src/concurrency/send-sync/examples.md:7
msgid ""
@ -14867,22 +15026,32 @@ msgid ""
"* `Mutex<T>`: Explicitly thread-safe via internal locking.\n"
"* `AtomicBool`, `AtomicU8`, ...: Uses special atomic instructions."
msgstr ""
"* `i8`、`f32`、`bool`、`char`、`&str`…\n"
"* `(T1, T2)`、`[T; N]`、`&[T]`、`struct { x: T }`…\n"
"* `String`、`Option<T>`、`Vec<T>`、`Box<T>`…\n"
"* `Arc<T>`:明确通过原子引用计数实现线程安全。\n"
"* `Mutex<T>`:明确通过内部锁定实现线程安全。\n"
"* `AtomicBool`、`AtomicU8`…:使用特殊的原子指令。"
#: src/concurrency/send-sync/examples.md:14
msgid ""
"The generic types are typically `Send + Sync` when the type parameters are\n"
"`Send + Sync`."
msgstr ""
"当类型参数为 `Send + Sync` 时,泛型类型通常\n"
"为 `Send + Sync`。"
#: src/concurrency/send-sync/examples.md:17
msgid "## `Send + !Sync`"
msgstr ""
msgstr "## `Send + !Sync`"
#: src/concurrency/send-sync/examples.md:19
msgid ""
"These types can be moved to other threads, but they're not thread-safe.\n"
"Typically because of interior mutability:"
msgstr ""
"这些类型可以移动到其他线程,但它们不是线程安全的。\n"
"这通常是由内部可变性造成的:"
#: src/concurrency/send-sync/examples.md:22
msgid ""
@ -14891,15 +15060,19 @@ msgid ""
"* `Cell<T>`\n"
"* `RefCell<T>`"
msgstr ""
"* `mpsc::Sender<T>`\n"
"* `mpsc::Receiver<T>`\n"
"* `Cell<T>`\n"
"* `RefCell<T>`"
#: src/concurrency/send-sync/examples.md:27
msgid "## `!Send + Sync`"
msgstr ""
msgstr "## `!Send + Sync`"
#: src/concurrency/send-sync/examples.md:29
msgid ""
"These types are thread-safe, but they cannot be moved to another thread:"
msgstr ""
msgstr "这些类型是线程安全的,但它们不能移动到另一个线程:"
#: src/concurrency/send-sync/examples.md:31
msgid ""
@ -14907,14 +15080,16 @@ msgid ""
"the\n"
" thread which created them."
msgstr ""
"* `MutexGuard<T>`:使用操作系统级别的原语(必须在创建这些原语的线程上\n"
"取消分配)。"
#: src/concurrency/send-sync/examples.md:34
msgid "## `!Send + !Sync`"
msgstr ""
msgstr "## `!Send + !Sync`"
#: src/concurrency/send-sync/examples.md:36
msgid "These types are not thread-safe and cannot be moved to other threads:"
msgstr ""
msgstr "这些类型不是线程安全的,不能移动到其他线程:"
#: src/concurrency/send-sync/examples.md:38
msgid ""
@ -14923,10 +15098,14 @@ msgid ""
"* `*const T`, `*mut T`: Rust assumes raw pointers may have special\n"
" concurrency considerations."
msgstr ""
"* `Rc<T>`:每个 `Rc<T>` 都具有对 `RcBox<T>` 的引用,其中包含\n"
"非原子引用计数。\n"
"* `*const T`、`*mut T`:Rust 会假定原始指针可能\n"
"在并发方面有特殊的注意事项。"
#: src/concurrency/shared_state.md:1
msgid "# Shared State"
msgstr ""
msgstr "# 共享状态"
#: src/concurrency/shared_state.md:3
msgid ""
@ -14934,6 +15113,8 @@ msgid ""
"is\n"
"primarily done via two types:"
msgstr ""
"Rust 使用类型系统来强制同步共享数据。这主要\n"
"通过两种类型实现:"
#: src/concurrency/shared_state.md:6
msgid ""
@ -14942,14 +15123,17 @@ msgid ""
" takes care to deallocate `T` when the last reference is dropped,\n"
"* [`Mutex<T>`][2]: ensures mutually exclusive access to the `T` value."
msgstr ""
"* [`Arc<T>`][1],对 `T` 进行原子计数:用于处理线程之间的共享,并负责\n"
"在最后一个引用被丢弃时取消分配 `T`。\n"
"* [`Mutex<T>`][2]:确保对 `T` 值的互斥访问。"
#: src/concurrency/shared_state/arc.md:1
msgid "# `Arc`"
msgstr ""
msgstr "# `Arc`"
#: src/concurrency/shared_state/arc.md:3
msgid "[`Arc<T>`][1] allows shared read-only access via `Arc::clone`:"
msgstr ""
msgstr "[`Arc<T>`][1] 允许通过 `Arc::clone` 实现共享只读权限:"
#: src/concurrency/shared_state/arc.md:5
msgid ""
@ -14973,6 +15157,25 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable\n"
"use std::thread;\n"
"use std::sync::Arc;\n"
"\n"
"fn main() {\n"
" let v = Arc::new(vec![10, 20, 30]);\n"
" let mut handles = Vec::new();\n"
" for _ in 1..5 {\n"
" let v = Arc::clone(&v);\n"
" handles.push(thread::spawn(move || {\n"
" let thread_id = thread::current().id();\n"
" println!(\"{thread_id:?}: {v:?}\");\n"
" }));\n"
" }\n"
"\n"
" handles.into_iter().for_each(|h| h.join().unwrap());\n"
" println!(\"v: {v:?}\");\n"
"}\n"
"```"
#: src/concurrency/shared_state/arc.md:29
msgid ""
@ -14989,16 +15192,27 @@ msgid ""
"detect them.\n"
" * `std::sync::Weak` can help."
msgstr ""
"* `Arc` 代表“原子引用计数”,它是使用原子操作的 `Rc` 的\n"
"线程安全版本。\n"
"* 无论 `T` 是否实现 `Clone`,`Arc<T>` 都会实现 `Clone`。如果 `T` 实现了 "
"`Send` 和 `Sync`,`Arc<T>` 便会\n"
"实现二者。\n"
"* `Arc::clone()` 在执行原子操作方面有开销,但在此之后,`T` 便可\n"
"随意使用,而没有任何开销。\n"
"* 请警惕引用循环,`Arc` 不会使用垃圾回收器检测引用循环。\n"
"* `std::sync::Weak` 对此有所帮助。"
#: src/concurrency/shared_state/mutex.md:1
msgid "# `Mutex`"
msgstr ""
msgstr "# `互斥器 (Mutex)`"
#: src/concurrency/shared_state/mutex.md:3
msgid ""
"[`Mutex<T>`][1] ensures mutual exclusion _and_ allows mutable access to `T`\n"
"behind a read-only interface:"
msgstr ""
"[`Mutex<T>`][1] 能够确保互斥,并允许对只读接口\n"
"后面的 `T` 进行可变访问:"
#: src/concurrency/shared_state/mutex.md:6
msgid ""
@ -15018,12 +15232,29 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable\n"
"use std::sync::Mutex;\n"
"\n"
"fn main() {\n"
" let v = Mutex::new(vec![10, 20, 30]);\n"
" println!(\"v: {:?}\", v.lock().unwrap());\n"
"\n"
" {\n"
" let mut guard = v.lock().unwrap();\n"
" guard.push(40);\n"
" }\n"
"\n"
" println!(\"v: {:?}\", v.lock().unwrap());\n"
"}\n"
"```"
#: src/concurrency/shared_state/mutex.md:22
msgid ""
"Notice how we have a [`impl<T: Send> Sync for Mutex<T>`][2] blanket\n"
"implementation."
msgstr ""
"请注意我们如何设置 [`impl<T: Send> Sync for Mutex<T>`][2] 通用\n"
"实现。"
#: src/concurrency/shared_state/mutex.md:31
msgid ""
@ -15045,10 +15276,24 @@ msgid ""
"to recover the data\n"
" regardless."
msgstr ""
"* Rust 中的互斥器看起来就像只包含一个元素的集合,其中的元素就是受保护的数"
"据。\n"
"* 在访问受保护的数据之前不可能忘记获取互斥量。\n"
"* 你可以通过获取锁,从 `&Mutex<T>` 中获取 `&mut T`。`MutexGuard` 能够确保 "
"`&mut T`\n"
"存在的时间不会比持有锁的时间更长。\n"
"* 如果 `T` 实现了 `Send`,`Mutex<T>` 便会实现 `Send` 和 `Sync`。\n"
"* 读写锁版本 - `RwLock`。\n"
"* 为什么 `lock()` 会返回 `Result`?\n"
"* 如果持有 `Mutex` 的线程发生panic,`Mutex` 便会“中毒”并发出信号,\n"
"表明其所保护的数据可能处于不一致状态。对中毒的互斥量调用 `lock()` 将会失"
"败,\n"
"并将显示 [`PoisonError`]。无论如何,你可以对该错误调用 `into_inner()` 来\n"
"恢复数据。"
#: src/concurrency/shared_state/example.md:3
msgid "Let us see `Arc` and `Mutex` in action:"
msgstr ""
msgstr "让我们看看 `Arc` 和 `Mutex` 的实际效果:"
#: src/concurrency/shared_state/example.md:5
msgid ""
@ -15068,10 +15313,25 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable,compile_fail\n"
"use std::thread;\n"
"// use std::sync::{Arc, Mutex};\n"
"\n"
"fn main() {\n"
" let v = vec![10, 20, 30];\n"
" let handle = thread::spawn(|| {\n"
" v.push(10);\n"
" });\n"
" v.push(1000);\n"
"\n"
" handle.join().unwrap();\n"
" println!(\"v: {v:?}\");\n"
"}\n"
"```"
#: src/concurrency/shared_state/example.md:23
msgid "Possible solution:"
msgstr ""
msgstr "可能有用的解决方案:"
#: src/concurrency/shared_state/example.md:25
msgid ""
@ -15099,10 +15359,33 @@ msgid ""
"}\n"
"```"
msgstr ""
"```rust,editable\n"
"use std::sync::{Arc, Mutex};\n"
"use std::thread;\n"
"\n"
"fn main() {\n"
" let v = Arc::new(Mutex::new(vec![10, 20, 30]));\n"
"\n"
" let v2 = Arc::clone(&v);\n"
" let handle = thread::spawn(move || {\n"
" let mut v2 = v2.lock().unwrap();\n"
" v2.push(10);\n"
" });\n"
"\n"
" {\n"
" let mut v = v.lock().unwrap();\n"
" v.push(1000);\n"
" }\n"
"\n"
" handle.join().unwrap();\n"
"\n"
" println!(\"v: {v:?}\");\n"
"}\n"
"```"
#: src/concurrency/shared_state/example.md:49
msgid "Notable parts:"
msgstr ""
msgstr "值得注意的部分:"
#: src/concurrency/shared_state/example.md:51
msgid ""
@ -15115,6 +15398,11 @@ msgid ""
"* Blocks are introduced to narrow the scope of the `LockGuard` as much as "
"possible."
msgstr ""
"* `Arc` 和 `Mutex` 中都封装了 `v`,因为它们的关注点是正交的。\n"
"* 将 `Mutex` 封装在 `Arc` 中是一种在线程之间共享可变状态的常见模式。\n"
"* `v: Arc<_>` 必须先克隆为 `v2`,然后才能移动到另一个线程中。请注意,lambda "
"签名中添加了 `move`。\n"
"* 我们引入了块,以尽可能缩小 `LockGuard` 的作用域。"
#: src/exercises/concurrency/morning.md:3
msgid "Let us practice our new concurrency skills with"