mirror of
https://github.com/KaiserY/trpl-zh-cn
synced 2024-11-09 00:43:59 +08:00
那么如果
This commit is contained in:
parent
201565cf20
commit
b0a5c825ab
@ -123,7 +123,7 @@ $ ./main # or .\main.exe on Windows
|
||||
|
||||
Cargo 是 Rust 的构建系统和包管理工具,同时 Rustacean 们使用 Cargo 来管理他们的 Rust 项目,因为它使得很多任务变得更轻松。例如,Cargo 负责构建代码、下载代码依赖的库并编译这些库。我们把代码需要的库叫做 **依赖**(*dependencies*)。
|
||||
|
||||
最简单的 Rust 程序,例如我们刚刚编写的,并没有任何依赖,所以目前我们只使用了 Cargo 负责构建代码的那一部分。随着编写更加复杂的 Rust 程序,你会想要添加依赖,那么如果你使用 Cargo 开始的话,这将会变得简单许多。
|
||||
最简单的 Rust 程序,例如我们刚刚编写的,并没有任何依赖,所以目前我们只使用了 Cargo 负责构建代码的那一部分。随着编写更加复杂的 Rust 程序,你会想要添加依赖,如果你使用 Cargo 开始的话,这将会变得简单许多。
|
||||
|
||||
由于绝大部分 Rust 项目使用 Cargo,本书接下来的部分将假设你使用它。如果使用安装章节介绍的官方安装包的话,Rust 自带 Cargo。如果通过其他方式安装 Rust 的话,可以在终端输入如下命令检查是否安装了 Cargo:
|
||||
|
||||
|
@ -58,7 +58,7 @@ fn calculate_length(s: &String) -> usize { // s is a reference to a String
|
||||
|
||||
我们将获取引用作为函数参数称为**借用**(*borrowing*)。正如现实生活中,如果一个人拥有某样东西,你可以从它哪里借来。当你使用完毕,必须还回去。
|
||||
|
||||
那么如果我们尝试修改借用的变量呢?尝试列表 4-9 中的代码。剧透:这行不通!
|
||||
如果我们尝试修改借用的变量呢?尝试列表 4-9 中的代码。剧透:这行不通!
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
@ -223,7 +223,7 @@ let s = &hello[0..4];
|
||||
|
||||
这里,`s`是一个`&str`,它包含字符串的头四个字节。早些时候,我们提到了这些字母都是两个字节长的,所以这意味着`s`将会是“Зд”。
|
||||
|
||||
那么如果获取`&hello[0..1]`会发生什么呢?回答是:在运行时会 panic,就跟访问 vector 中的无效索引时一样:
|
||||
如果获取`&hello[0..1]`会发生什么呢?回答是:在运行时会 panic,就跟访问 vector 中的无效索引时一样:
|
||||
|
||||
|
||||
```text
|
||||
|
@ -258,11 +258,11 @@ std::marker::Send` is not satisfied
|
||||
|
||||
哇哦,太长不看!说重点:第一个提示表明 `Rc<Mutex<i32>>` 不能安全的在线程间传递。理由也在错误信息中,“不满足 `Send` trait bound”(`the trait bound Send is not satisfied`)。下一部分将会讨论 `Send`,它是确保许多用在多线程中的类型,能够适合并发环境的 trait 之一。
|
||||
|
||||
不幸的是,`Rc<T>` 并不能安全的在线程间共享。当 `Rc<T>` 管理引用计数时,它必须在每一个 `clone` 调用时增加计数,并在每一个克隆被丢弃时减少计数。`Rc<T>` 并没有使用任何并发原语,来确保改变计数的操作不会被其他线程打断。在计数出错时可能会导致诡异的 bug,比如可能会造成内存泄漏,或在使用结束之前就丢弃一个值。那么如果有一个正好与 `Rc<T>` 类似,而又以一种线程安全的方式改变引用计数的类型会怎么样呢?
|
||||
不幸的是,`Rc<T>` 并不能安全的在线程间共享。当 `Rc<T>` 管理引用计数时,它必须在每一个 `clone` 调用时增加计数,并在每一个克隆被丢弃时减少计数。`Rc<T>` 并没有使用任何并发原语,来确保改变计数的操作不会被其他线程打断。在计数出错时可能会导致诡异的 bug,比如可能会造成内存泄漏,或在使用结束之前就丢弃一个值。如果有一个类型与 `Rc<T>` 相似,又以一种线程安全的方式改变引用计数,会怎么样呢?
|
||||
|
||||
#### 原子引用计数 `Arc<T>`
|
||||
|
||||
如果你想过之前的问题,答案是肯定的,确实有一个类似`Rc<T>`并可以安全的用于并发环境的类型:`Arc<T>`。字母“a”代表**原子性**(*atomic*),所以这是一个**原子引用计数**(*atomically reference counted*)类型。原子性是另一类这里还未涉及到的并发原语;请查看标准库中`std::sync::atomic`的文档来获取更多细节。其中的要点就是:原子性类型工作起来类似原始类型,不过可以安全的在线程间共享。
|
||||
答案是肯定的,确实有一个类似`Rc<T>`并可以安全的用于并发环境的类型:`Arc<T>`。字母“a”代表**原子性**(*atomic*),所以这是一个**原子引用计数**(*atomically reference counted*)类型。原子性是另一类这里还未涉及到的并发原语;请查看标准库中`std::sync::atomic`的文档来获取更多细节。其中的要点就是:原子性类型工作起来类似原始类型,不过可以安全的在线程间共享。
|
||||
|
||||
为什么不是所有的原始类型都是原子性的?为什么不是所有标准库中的类型都默认使用`Arc<T>`实现?线程安全带来性能惩罚,我们希望只在必要时才为此买单。如果只是在单线程中对值进行操作,原子性提供的保证并无必要,代码可以因此运行的更快。
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user