![]() |
1
10
你的例子很好用。 多处理器使用 coherency protocol 如 MESI 以确保数据在缓存之间保持同步。对于MESI,每个缓存线都被认为是被修改、独占、在CPU之间共享的,或者是无效的。写一条在处理器之间共享的缓存线会强制它在另一个CPU中无效,从而保持缓存的同步。 然而,这还不够。不同的处理器有不同的 memory models 和大多数现代处理器支持某种程度的重新排序内存访问。在这些情况下, memory barriers 是需要的。 例如,如果您有线程A:
线程B:
由于这两个处理器都在不同的处理器上运行,因此无法保证在线程B看到DoWork()内完成的写入操作之后,对WorkDone和DoSomethingWithResults()的写入操作将以潜在的不一致状态继续进行。内存屏障保证了读和写的某些顺序——在线程A中的dowork()之后添加一个内存屏障将强制dowork完成的所有读/写操作在write to workdone之前完成,这样线程B将获得一致的视图。互斥锁本质上提供了一个内存屏障,这样读/写就不能通过调用来锁定和解锁。 在您的情况下,一个处理器会向其他处理器发出信号,指出它弄脏了缓存线,并强制其他处理器从内存重新加载。获取互斥量以读取和写入该值,可以保证对内存的更改对其他处理器是可见的,并且是按预期的顺序进行的。 |
![]() |
2
1
大多数锁原语如互斥体意味着 memory barriers . 这些强制执行缓存刷新和重新加载。 例如,
|
![]() |
3
0
一般来说,编译器理解共享内存,并花费大量精力确保将共享内存放置在可共享的位置。现代编译器在排序操作和内存访问方面非常复杂;它们倾向于理解线程和共享内存的本质。这并不是说它们是完美的,但一般来说,编译器会处理大部分问题。 |
![]() |
4
0
C对此类问题有一些内置支持。
您可以用
另一部分是围绕名为threading.monitor.enter(x)和threading.monitor.exit(x)的.NET方法的语法包装器,其中x是要锁定的变量。这会导致试图锁定X的其他线程必须等待,直到锁定线程调用退出(X)。
|