在单 CPU、单核 CPU 上,你仍然可以拥有线程 多任务处理(多线程),但要注意由于缺少多个执行单元,通常只能同时执行一个线程。没有多个执行单元(硬件多线程),硬件依赖于内核定义的“软件多线程”策略——低级操作系统软件来确定何时执行什么。
抢占是一种策略,它涉及更积极地引导(可以这么说)这些多个执行流沿着单个路径进行,通常部分通过使用基于定时器的中断来实现。与抢占相反的合作调度采用更加自由放任的方法,将其完全交给活动线程来发出信号。
作为结果,合作调度方案允许一个线程进程的线程更长时间地持有唯一的计算资源(在这种情况下)。
但是,如果这种方案中的活动线程想永远保持活动状态怎么办?这本质上就是发生的情况。
自旋锁是一种主动等待以锁定请求的资源。线程将一直等待其他线程释放它想要的资源。正如文本所指出的硬件情况只允许一条活动线程,因此,如果请求的资源被锁定,则意味着它被非活动线程锁定。
在没有抢占的情况下,线程决定何时停止执行。因此,当活动线程自旋锁定时,它将永远坐在那里--也就是所谓的挂起。为了停止这个过程,用户可能需要强制关闭系统并清除缓存/动态内存。
使用抢占式调度,线程被实现为时间片。当访问特定资源是在一个线程中完成进一步工作的必要条件时,自旋锁--繁忙等待--是有意义的。
使用抢占式调度,内核会在指定时间后自动强制上下文切换,因此即使只有一个CPU,也不会出现停顿。最终,拥有资源锁定的线程将获得一些时间并释放其资源。当自旋锁线程获得其下一个调度时间时,它将能够锁定资源并继续执行。
总体而言,这意味着减少了停顿。
然而,自旋锁仍可能遇到更复杂的抢占式调度问题,例如死锁... 当两个线程同时持有对方的资源并被自旋锁定:
然而,通过内核对资源锁定请求的保护,这种情况通常是可以避免的。
在一个完美的世界中,通过谨慎的线程设计和合作调度,可能会导致关键进程的执行速度更快。因此,在像Mac OS和Windows 3.x这样的老操作系统中,这是一种常见的方法。然而,随着计算需求的增加,避免协作调度的缺点变得越来越困难,因此几乎所有现代操作系统内核都使用抢占式调度器。