互斥锁是否保证线程总是将更新的值存储到主内存中?

Does a mutex lock guarantee that a thread will always store updated values into the main memory?

一个。使用互斥锁访问内存位置是否意味着无论关键代码对互斥变量做什么,最终都会进入主内存,并且不仅在线程的缓存或寄存器中更新而没有主内存中值的新副本?

b。如果是这样的话,我们不是有效地 运行 关键核心就好像我们没有缓存(至少没有互斥锁变量的缓存位置)吗?

c。如果是这种情况,那么关键代码不是重量级代码,需要尽可能小,考虑到至少在互斥量的开始和结束时继续需要从主内存读取和写入-锁定会话?

a. Does accessing a memory location with a mutex lock mean that whatever the critical code is doing to the mutexed-variables will end up into the main memory, and not only updated inside the thread's cache or registers without a fresh copy of values in the main memory?

正确实现的互斥锁保证在释放互斥锁时,其他代理(例如其他 CPUs)可以看到以前的写入。在具有高速缓存一致性(例如 80x86)的系统上,修改在高速缓存中时是可见的,并且修改是否已到达主内存并不重要。

本质上(过度简化),为了缓存一致性,当另一个 CPU 想要修改后的数据时,它会广播一个请求(比如“嘿,我想要地址 123456 处的数据”),如果它在另一个 CPU 的缓存中,另一个 CPU 响应“这是你想要的数据”,如果数据不在任何缓存中,内存控制器响应“这是你想要的数据”;并且 CPU 获取最新版本的数据,而不管数据在哪里或响应请求的是什么。实际上,它要复杂得多——如果您有兴趣,我建议您阅读 MESI 缓存控制协议 (https://en.wikipedia.org/wiki/MESI_protocol)。

b. If that's the case, aren't we effectively running the critical core as if we didn't have a cache (at least no cache locations for mutex-lock variables)?

如果是这种情况(例如,如果没有缓存一致性);某些东西(释放互斥锁的代码)必须确保在互斥锁可以被其他东西获取之前将修改后的数据写回 RAM。这不会阻止缓存在临界区内使用(例如临界区可以写入缓存,然后修改后的数据可以从缓存发送到 RAM)。

成本取决于多种因素(CPU速度、缓存速度和内存速度,以及缓存是“回写”还是“直写”,以及修改了多少数据)。对于某些情况(相对较慢 CPU 使用直写缓存)成本可能几乎为零。

c. And if that is the case then isn't the critical code a heavy weight code, and needs to be as small as possible, considering the continued need to read from and write into the main memory at least at the beginning and end of the mutex-locking session?

没有不使用缓存那么重

同步访问(不管它是如何完成的)总是比不同步访问(并且崩溃,因为你所有的数据都搞砸了)更昂贵。 ;-)

多线程代码的挑战之一是在同步成本和并行性之间找到一个很好的折衷 - 少量锁(或单个全局锁)降低了同步成本但限制了并行性(线程获取什么都不做等待获取锁);并且大量的锁会增加同步的成本(例如,获取更多的锁比获取一个锁更昂贵)但允许更多的并行性。

当然,并行性也受到您拥有的 CPU 数量的限制;这意味着对一个系统(CPUs 很少)的妥协可能对另一个系统(CPUs 很多)来说不是一个好的妥协。