40 线程

Emacs Lisp 提供一种有限形式的并发机制,称为 线程(threads)。Emacs 单个实例中的所有线程共享同一块内存。 Emacs Lisp 中的并发为 “基本协作式(mostly cooperative)”,意味着 Emacs 仅会在明确规定的时机 在不同线程间切换执行。不过,Emacs 的线程支持在设计上已为后续支持更细粒度的并发 做好了准备,正确的程序不应依赖协作式线程。

目前,线程切换会在以下场景发生:通过 thread-yield 显式请求时、 等待键盘输入或异步进程的输出时(例如在 accept-process-output 期间), 或是在与线程相关的阻塞操作中,如互斥锁加锁或 thread-join

Emacs Lisp 提供创建和控制线程的原语,同时也支持创建和控制互斥锁与条件变量, 这些常用于线程同步。

全局变量在所有 Emacs Lisp 线程间共享,而局部变量则不共享—动态的 let 绑定是线程局部的。每个线程还拥有各自的当前缓冲区(see 当前缓冲区) 以及各自的匹配数据(see 匹配数据)。

注意,Emacs Lisp 实现会对 let 绑定做特殊处理。 除使用 let 之外,无法复制这种变量入栈与恢复的行为。 例如,用 unwind-protect 手动实现的 let 无法让变量值 具备线程局部特性。

对于词法绑定(see Scoping 变量绑定的作用域规则),闭包在 Emacs Lisp 中 与其他对象无异,闭包中的绑定会被所有调用该闭包的线程共享。