2022-02-05_星期六

后端技术面试 38 讲

阳底下没有新鲜事,绝大多数新技术其实都脱胎于一些既有的技术体系。

程序运行时如果需要创建数组等数据结构,操作系统就会在进程的堆空间申请一块相应的内存空间,并把这块内存的首地址信息记录在进程的栈中。

每次函数调用,操作系统都会在栈中创建一个栈帧(stack frame)。

真正执行的函数永远都在栈顶。而且因为栈帧是隔离的,所以不同函数可以定义相同的变量而不会发生混乱。

一台计算机服务器同时处理多个计算任务主要依靠的是操作系统的 CPU 分时共享技术。

进程在生命周期中,主要有三种状态,运行、就绪、阻塞:

  • 运行:当一个进程在 CPU 上运行时,则称该进程处于运行状态。处于运行状态的进程的数目小于等于 CPU 的数目。
  • 就绪:当一个进程获得了除 CPU 以外的一切所需资源,只要得到 CPU 即可运行,则称此进程处于就绪状态,就绪状态有时候也被称为等待运行状态。
  • 阻塞:也称为等待或睡眠状态,当一个进程正在等待某一事件发生(例如等待 I/O 完成,等待锁……)而暂时停止运行,这时即使把 CPU 分配给进程也无法运行,故称该进程处于阻塞状态。

陈天 · Rust 编程第一课

Weak 相当于一个弱化版本的 Rc,不参与到引用计数的计算中,而 Weak 可以 upgrade 到 Rc 来使用。它可以帮我们打破循环引用。

函数返回引用时,除非是静态引用,那么这个引用一定和带有引用的某个输入参数有关。

&self / &mut self 出现时,返回值的生命周期和它关联

当你要返回在函数执行过程中,创建的或者得到的数据,和参数无关,那么无论它是一个有所有权的数据,还是一个引用,你只能返回带所有权的数据。对于引用,这就意味着调用 clone() 或者 to_owned() 来,从引用中得到所有权。

&strString 的切片,也可以是 &str 的切片。它和 &[T] 一样,没有什么特别的,就是一个带着长度的胖指针,指向了一片连续的内存区域。

切片之于 Vec<T> / String 等数据,就好比数据库里的视图(view)之于表(table)。

如果你的确想用可写的全局变量,可以用 Mutex,然而,初始化它很麻烦,这时,你可以用一个库 lazy_static

消息队列高手课

哪些问题适合使用消息队列来解决?

  1. 异步处理
  2. 流量控制
  3. 服务解耦
  4. 其他:
    • 作为发布 / 订阅系统实现一个微服务级系统间的观察者模式;
    • 连接流计算任务和数据;
    • 用于将消息广播给大量接收者。

令牌桶控制流量的原理是:单位时间内只发放固定数量的令牌到令牌桶中,规定服务在处理请求之前必须先从令牌桶中拿出一个令牌,如果令牌桶中没有令牌,则拒绝请求。

Rust 权威指南

Rust 中的闭包是一种可以存入变量或作为参数传递给其他函数的匿名函数。

和一般的函数不同,闭包可以从定义它的作用域中捕获值。

我们希望在程序中将代码定义在一处,但只在真正需要结果时才执行相关代码。而这正是闭包的用武之地!

闭包的定义放置在=之后,它会被赋值给语句左侧的 expensive_closure 变量。为了定义闭包,我们需要以一对竖线(|)开始,并在竖线之间填写闭包的参数;之所以选择这样的写法是因为它与 Smalltalk 及 Ruby 中的闭包定义类似。

1
2
3
4
5
let expensive_closure = |num| {
    println!("calculating slowly...");
    thread::sleep(Duration::from_secs(2));
    num
};

和 fn 定义的函数不同,闭包并不强制要求你标注参数和返回值的类型。

为了在结构体、枚举或函数参数中使用闭包,我们需要使用泛型及 trait 约束。

1
2
3
4
5
6
struct Cacher<T>
    where T: Fn(u32) -> u32
{
    calculation: T,
    value: Option<u32>,
}

闭包还有一项函数所不具备的功能:它们可以捕获自己所在的环境并访问自己被定义时的作用域中的变量。

当闭包从环境中捕获值时,它会使用额外的空间来存储这些值以便在闭包体内使用。

3 种 Fn 系列的 trait:

  • FnOnce 意味着闭包可以从它的封闭作用域中,也就是闭包所处的环境中,消耗捕获的变量。
  • FnMut 可以从环境中可变地借用值并对它们进行修改。
  • Fn 可以从环境中不可变地借用值。

当你创建闭包时,Rust 会基于闭包从环境中使用值的方式来自动推导出它需要使用的 trait。

  • 所有闭包都自动实现了 FnOnce,因为它们至少都可以被调用一次。
  • 那些不需要移动被捕获变量的闭包还会实现 FnMut
  • 而那些不需要对被捕获变量进行可变访问的闭包则同时实现了 Fn。

假如你希望强制闭包获取环境中值的所有权,那么你可以在参数列表前添加 move 关键字。这个特性在把闭包传入新线程时相当有用,它可以将捕获的变量一并移动到新线程中去。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
fn main() {
    let x = vec![1, 2, 3];

    let equal_to_x = move |z| z == x;

    // println!("can't use x here: {:?}", x);

    let y = vec![1, 2, 3];

    assert!(equal_to_x(y));
}

在大部分情形下,当你需要指定某一个 Fn 系列的 trait 时,可以先尝试使用 Fn trait,编译器会根据闭包体中的具体情况来告诉你是否需要 FnMut 或 FnOnce。

我们为什么睡觉

每晚的规律睡眠少宇 6~7 个小时会破坏你的免疫系统,罹患癌症的风险将增加一倍以上。

睡眠太少会提升让你感到饥饿的激素的浓度,同时抑制产生饱腹感的激素浓度。

人类是实际上是唯一一种会在没有合理益处的情况下故意剥夺自己睡眠的物种。

睡眠慷慨地为我们的心理健康服务,重新校准大脑中的情感回路,使我们第二天能沉着冷静地应对人际和心理方面的各种挑战。

梦为所有有幸能够做梦的物种(包括人类在内)提供了一套独特的福利,包括能够抚慰痛苦记忆、安抚大脑的神经化学物质浸浴,以及提供一个虚拟现实空间,大脑可以在其中融合过去和现在的知识,激发创造力。

要想使我们的大脑和身体健康恢复到每天最佳的状态,我们唯一能做的也就是最有效的事,就是睡觉,它是大自然词语我们的对抗死亡的最佳办法。

患者只有在满足以下所有条目的情况下才算会被诊断为失眠症:

  • 对睡眠量或睡眠质量不满意(例如入睡困难、睡眠间断、醒的过早等)
  • 感到严重不适,或正常生活受到负面影响
  • 超过三个月,每周至少失眠三晚
  • 没有其他可能并发失眠症装的精神障碍或疾病

现实中典型的失眠患者实际上长期因一下状况而感到困扰:难以入睡,半夜醒来,早上醒得太早,醒后难以入睡,在清醒的时间里感到精神不济。

慢性失眠最常见的两个原因是心理上的:

  1. 情绪困扰或担忧
  2. 情绪失落或焦虑
updatedupdated2022-03-092022-03-09