您可以在此链接中看到一个有趣的表格。 http://norvig.com/21-days.html#answers
描述的表格,
互斥锁定/解锁 25 nanosec
从主内存中获取 100 nanosec
纳秒?
我感到很惊讶,因为mutex lock
比fetch data from memory
快。如果是这样,mutex lock
究竟做了什么? Mutex lock
在桌上意味着什么?
答案 0 :(得分:15)
让我们说十个人不得不分享一支笔(也许他们在一家资金紧张的公司工作)。因为他们必须用笔写很长的文档,但是写文档的大部分工作只是考虑说什么,他们同意每个人都用笔写一个文档的句子,然后必须让其他人可以使用。
现在我们遇到了一个问题:如果有两个人在考虑下一个句子,并且两个人都想立刻使用笔会怎么样?我们可以说,两个人都可以拿笔,但这是一支脆弱的老笔,所以如果两个人抓住它,那么它就会破坏。相反,我们在笔周围画一条粉笔线。首先,你把手放在粉笔线上,然后你抓住笔。如果一个人的手在粉笔线内,那么没有其他人可以将他们的手放在粉笔线内。如果两个人试图同时将手放在粉笔线上,根据这些规则,其中只有一个会首先进入粉笔线,所以另一个人必须拉回他们的手并将其保持在粉笔线之外,直到笔可以再次使用。
让我们将其与互斥体联系起来。互斥锁是一种在短时间内保护共享资源(笔)的方法,称为关键部分(写入文档的一个句子的时间)。无论何时您想使用该资源,您都同意先致电mutex_lock
(将您的手放在粉笔线内)。无论何时完成资源,您都同意致电mutex_unlock
(从粉笔行区域拿出手)。
现在了解互斥体的实现方式。互斥锁通常用共享内存实现。有一些共享的不透明数据对象称为互斥锁,mutex_lock
和mutex_unlock
函数都指向其中一个。 mutex_lock
函数使用原子测试和设置或加载链接/存储条件指令序列检查和修改互斥锁内的数据(通常使用x86,xhcg
),并且“获取”互斥锁“ - 设置互斥锁对象的内容,以向其他线程指示关键部分被锁定 - 或必须等待。最终,线程获取互斥锁,在临界区内完成工作,并调用mutex_unlock
。此函数设置互斥锁内的数据以将其标记为可用,并可能唤醒一直尝试获取互斥锁的休眠线程(这取决于互斥锁实现 - mutex_lock
的某些实现只是在紧密的外观中旋转在xchg
上,直到互斥锁可用,因此mutex_unlock
无需通知任何人。
为什么锁定互斥锁会比走出内存更快?简而言之,缓存。 CPU具有可以非常快速地访问的高速缓存,因此只要处理器可以确保没有其他处理器访问该数据,xchg
操作就不需要一直到存储器。但是x86有一个“拥有”缓存行的概念 - 如果处理器0拥有一个缓存行,那么任何其他想要使用该缓存行中的数据的处理器必须通过处理器0.这样就不需要{ {1}}查看缓存之外的任何数据的操作,缓存访问往往非常快,因此获取无争用的互斥锁比内存访问更快。
最后一段有一点需要注意:速度优势仅适用于无争议的互斥锁。如果两个线程试图同时锁定相同的互斥锁,则运行这些线程的处理器必须通信并处理相关缓存线的所有权,这大大减慢了互斥锁的获取速度。此外,两个线程中的一个必须等待另一个线程执行临界区中的代码,然后释放互斥锁,从而进一步减慢其中一个线程的互斥锁获取速度。
答案 1 :(得分:1)
你链接的文章没有提到架构,但从L1和L2缓存的提及判断它是英特尔。如果是这样,那么我认为通过互斥锁它们意味着LOCK指令。在这方面,这篇文章似乎很相关:Intel 64 and IA-32 | Atomic operations including acquire / release semantic
如果你知道,你正在寻找什么,Intel software developer's manual也可以提供帮助。我读过关于LOCK指令的任何相关信息。