【发布时间】:2018-01-19 02:39:25
【问题描述】:
我了解在单核处理器中使用 信号量 可以轻松完成同步。但是在多核的情况下,如果多个进程想在同一时刻进入临界区,是全部进入临界区还是只有一个获胜?获胜者过程获胜的标准是什么?
【问题讨论】:
标签: process parallel-processing x86 operating-system
我了解在单核处理器中使用 信号量 可以轻松完成同步。但是在多核的情况下,如果多个进程想在同一时刻进入临界区,是全部进入临界区还是只有一个获胜?获胜者过程获胜的标准是什么?
【问题讨论】:
标签: process parallel-processing x86 operating-system
当两个内核尝试同时进入临界区时,它们都尝试同时写入内存中的信号量,使用锁定的读-修改-写操作。为了让内核完成写入,缓存必须获得对包含信号量的缓存行的独占访问权限。这会强制另一个核心将该行标记为无效。缓存协议确保只有一个内核可以获得独占访问,并且该内核进入临界区。
同时,另一个也在尝试写入信号量的内核必须等待,因为它仍然需要独占访问高速缓存行。一旦第一个核心完成其写入操作,另一个核心将获得独占访问权限并可以完成其读取-修改-写入。但是 read-modify-write 的结果告诉它信号量很忙,所以它不能进入临界区,直到它检测到信号量已经被释放。
【讨论】:
即使存在多个内核,信号量(或互斥体,或大多数其他同步原语)的工作方式也一样 - 只有指定数量的线程可以进入信号量。如果它只在单处理器机器上工作,它确实是一个糟糕的信号量!
要完成这项工作需要多种机制,我将尝试给出一个高层次的观点。
请注意,内存仍然在不同的内核之间共享。 CMPXCHG instruction 是了解如何使用共享内存同步内核的一种简化但 IMO 有用的方法。该指令可以原子地(请参阅下面的更多详细信息)比较和设置内存地址。如果内存地址具有您要比较的值,它还将零标志设置为 1。
考虑以下代码:
wait:
mov eax, 0
mov ecx, 1
lock cmpxchg [address of lock], ecx
jne wait
// We now own the lock
代码在逻辑上循环执行以下操作:仅当 lock 为 0 时才将 lock 的值设置为 1。
这段代码可以多核运行,cmpxchg的原子性保证只有一个核获胜。
如果每个核心都有自己的缓存(现在通常是这种情况),情况会变得更加复杂。对于单独的缓存,每个内核都有自己的内存视图,因此必须注意确保这些内存视图是一致的。简短的回答是,这可以通过让缓存在数据更改时相互通知来完成,以便其他缓存可以在需要时使它们的副本无效或更新。查阅窥探和 MESI 协议以了解更多详细信息。
请注意,如果内核在同一个物理芯片上,那么它们都在竞争内存总线,并且内核之间有共享它的机制(例如仲裁机制;另请参阅LOCK 指令)。
【讨论】:
信号量只是在一个系统中通过线程进行信号化的一种方式。您可以在不影响其使用的单核或多核 CPU 中使用信号量。
现在让我们回到您的问题。如果您有关键部分并且多个线程想要进入该区域,它们将全部进入该区域。您需要了解主线程(例如)或将启动它们的其他线程,在它们之间产生一些时间间隔(大约几个 ns 的时间空间非常小)。 这就是我们使用 signalisation 的原因,因为我们不想要“赢家”,另一方面,在几乎所有情况下,线程都可能在该关键部分进行不必要的更改。
在单核系统中,您只能实现仅并发的进程调度(假并行,通过 TaskScheduler ),因为不同的线程必须通过分配的时隙共享核心。
【讨论】: