围绕单个字读写的互斥体
如果您有一个多线程应用程序,并且在线程之间共享一个字变量(即 - 32 位系统上的 32 位数据类型),是否有必要使用互斥锁来保护对该字的读取和写入?
If you have a multi-threaded application with a word variable shared between threads (ie - 32-bit data type on a 32-bit system), is it necessary to protect reads and writes to that word with a mutex?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

我不会谈论缓存、多核、乱序执行等。我只会提供一个简单的示例来说明为什么您想要使用互斥锁(或其他一些互斥技术,例如中断操作等)。 )
为了将变量加一(至少在我现在处理的大多数架构上),您必须将值从内存读取到寄存器,调整寄存器中的值,然后将其写回内存。假设我们有 2 个线程,高优先级 A 和低优先级 B。采用以下场景:
现在两个线程都增加了该值,但只增加了 1。
如果这是电梯楼层号、感测到的心跳次数或航天飞机倒计时值(好吧,这将是一个减量),我们可能会遇到问题。
请注意,有些架构(通常是 CISC)可以原子地执行此增量操作,最好不要做出此假设(您好,可移植性和正确性)。
注意:在某些情况下 - 但不要这样做 - 如果您有一个编写器和一个编写器,那么您可以在没有互斥体的情况下逃脱。多个读者。例如,ISR 可能会增加滴答计数或其他什么,而其他线程/任务则由 & 来实现。经常阅读它。
我想我想说的一点是,保护共享数据始终是一个好主意,即使您认为没有它也可以逃脱。如果你想“突击队”,你真的必须知道你在做什么,即使这样,相同的代码明天移植到新架构时也可能会崩溃。
Rather than talk about caches, multicore, out-of-order execution, etc. I'll just offer a simple example to illustrate why you'd want to use a mutex (or some other mutual exclusion technique, e.g. interrupt manipulation, etc.)
In order to increment a variable by one - at least on most architectures I deal with these days - you have to read the value from memory to a register, adjust the value in the register, and write it back to memory. Suppose we have 2 threads, high-priority A, and low priority B. Take this scenario:
Now both threads incremented the value, but it only went up by one.
If this was the elevator floor number, the number of heart beats sensed, or the space shuttle countdown value (OK, that would be a decrement), we might have ourselves a problem.
Note that there are some architectures (usually CISC) that can do this increment operation atomically, it's better to not make this assumption (hello, portability & correctness).
Note: In some cases - but don't do this - you can get away without a mutex if you have one writer & multiple readers. For example, maybe an ISR increments a tick count or whatever, and other threads/tasks come by & read it every so often.
I guess the point I want to make is that it's always a good idea to protect shared data, even if you think you can get away without it. If you want to "go commando", you REALLY have to know what you're doing, and even then, the same code could break tomorrow when it's ported to a new architecture.