我对互斥体如何工作感兴趣。我了解他们的目的,因为我找到的每个网站都解释了他们的所作所为,但我无法理解在这种情况下会发生什么:
有两个线程同时运行,它们试图同时锁定互斥锁。
这在单核上不会出现问题,因为这种情况永远不会发生,但在多核系统中,我认为这是一个问题。我看不出有任何方法可以防止这样的并发问题,但它们显然存在。
感谢您的帮助
答案 0 :(得分:8)
2个线程无法锁定系统范围的Mutex,一个将锁定,另一个将被阻止。
互斥锁/锁的语义!确保只能执行一个线程 在任何时候超越锁定电话。到达的第一个线程 该调用获取互斥锁上的锁定。任何以后的线程都会阻塞 在拨打互斥锁/锁!直到拥有锁的线程 使用互斥锁/解锁释放锁定。
就如何实现这一点而言,请查看test-and-set。
在计算机科学中,测试和设置指令是一条指令 用于写入内存位置并将其旧值作为a返回 单原子(即不可中断)操作。如果多个 进程可以访问相同的内存,如果进程当前 执行测试和设置,没有其他过程可以开始另一个 测试并设置直到第一个过程完成。 CPU可能会使用 其他电子元件提供的测试和设置指令 作为双端口RAM; CPU还可以提供测试和设置指令 自己。
如果旧值为0,则调用进程获取锁定。它旋转 将1写入变量,直到发生这种情况。
答案 1 :(得分:6)
正确实现互斥锁时,永远不能同时锁定互斥锁。为此,您需要一些具有有用属性的原子操作(保证在某一时刻发生在对象上的唯一操作)。
x86架构中的一个此类操作是xchg
(交换)。例如,xchg eax, [ebp]
将读取地址ebp
的值,将eax
中的值写入地址ebp
,然后将eax
设置为读取值,同时保证这些操作不会与对该地址的并发读写交错。
现在您可以实现互斥锁。要锁定,请将1
加载到eax
,使用互斥锁的值交换eax
,然后查看eax
。如果它是1
,它已被锁定,因此您可能想睡觉并稍后再试。如果是0
,则只需锁定互斥锁即可。要解锁,只需将0
的值写入互斥锁。
请注意,我在这里重点介绍了重要细节。例如,x86的xchg
足够原子,可以在单个处理器上进行先发制人的多任务处理。当您在多个处理器之间共享内存时(例如在多核系统中),除非您使用lock
前缀(例如lock xchg eax, [ebp]
,而不是xchg eax, [ebp]
,否则它是不够的。 ),ensures that only one processor can access that memory while the instruction is executed。