双向通信 在我们当前的客户端-服务器实现中,通信是单向的:从客户端到服务器。 客户端无法知道服务器是否收到了信息、执行成功还是失败。这并不理想。 为了解决这个问题,我们可以引入双向通信系统。 响应通道 我们需要一种方法让服务器向客户端发回响应。有多种方法可以做到这一点,但最简单的方法是
Interior mutability(内部可变性) 分析一下Sender的send签名 impl<T> Sender<T> { pub fn send(&self, t: T) -> Result<(), SendError<T>&g
Channels(通道) 到目前为止,我们生成的所有线程都相当短暂。获取输入、执行运算、返回结果、关闭。 对于我们的票据管理系统,我们希望采用不同的方式:客户端-服务器架构。 我们将有一个长期运行的服务器线程,负责管理我们的状态,即存储的票据。 然后,我们将有多个客户端线程。 每个客户
作用域线程 到目前为止,我们讨论过的所有生命周期问题都有一个共同的根源:生成的线程的生命周期可能超过其父线程。我们可以通过使用作用域线程来避免这个问题。 let v = vec![1, 2, 3]; let midpoint = v.len() / 2; std::thread::scope(|s
泄露数据 向生成的线程传递引用的主要问题是use-after-freebug:使用已经freed或de-allocated的指针访问数据。 如果我们使用的是堆分配的内存,我们可以通过告诉Rust永远不会回收该内存来避免这个问题:我们故意选择内存泄漏。 例如,可以使用 Rust 标准库中的 Box::
‘static 如果我们尝试在上一个练习中从Vec借用切片,我们可能会遇到下面的编译器错误: error[E0597]: `v` does not live long enough | 11 | pub fn sum(v: Vec<i32>) -> i32 {
Threads(线程) 在开始编写多线程代码之前,让我们退一步先学习一下什么是线程,以及为什么要使用线程。 什么是线程? 线程,是由底层操作系统管理的可执行上下文。每一个线程都有自己的堆栈和指令指针。 一个process(进程)可以管理多个th
线程——介绍 Rust的一大承诺就是无畏并发:让编写安全的并发程序变得更容易。我们还没有看到太多这一点。到目前位置,我们所做的所有工作都是单线程的。是时候开始学习多线程了。 在本章节,我们会将我们的票务商店变为多线程。我们将有机会接触Rust的大部分核心并发功能,包括:
概述 通过从Vec迁移到HashMap,我们提高了票务管理系统的性能,并在此过程中简化了代码。 不过,这并不意味着万事大吉。在迭代Vec的存储结构时,我们可以确保ticket按照添加的顺序返回。 HashMap的情况并非如此:我们可以迭代tickets,但是顺序是随机的。
HashMap(哈希表) 我们对Index/IndexMut的实现并不理想:我们需要按照id遍历整个Vec来检索想要的ticket;时间复杂度为O(n),其中n就是TicketStore里面ticket的数量。 我们可以通过使用不同的数据结构来存储ticket:HashM