设置一个位是否会与同一字上并发的其他位集发生冲突?
假设我有一个位图,并且多个线程(在多个 CPU 上运行)正在其上设置位。不使用同步,也不使用原子操作。此外,不进行任何重置。据我了解,当两个线程尝试在同一个字上设置两个位时,最终只会坚持一个操作。原因是,对于要设置的位,应该读取并写回整个字,因此当两个读取同时完成时,写回一个操作将覆盖另一个操作。这是正确的吗?
如果上述情况成立,那么字节操作也总是如此吗?也就是说,如果一个单词是 2 个字节,并且每个线程尝试将不同的字节设置为 1,那么它们在并发执行时是否也会相互覆盖,或者某些系统是否支持将结果写回单词的一部分?
询问的原因是试图弄清楚我必须放弃多少空间才能省略位/字节/字映射操作中的同步。
Say I have a bitmap, and several threads (running on several CPUs) are setting bits on it. No synchronization is used, and no atomic operations. Also, no resets are done. To my understanding, when two threads are trying to set two bits on the same word, only one operation would eventually stick. The reason is that for a bit to be set, the whole word should be read and written back, and so when both reads are done at the same time, when writing back one operation would override the other. Is that correct?
If the above is true, is it always so for byte operations as well? Namely, if a word is 2 bytes, and each thread tries to set a different byte to 1, will they too override each other when done concurrently, or do some systems support writing back the results to only a part of a word?
Reason for asking is trying to figure out how much space do I have to give up in order to omit synchronization in bit/byte/word-map operations.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
简而言之,它非常依赖于 CPU 和编译器。
假设您有一个包含零的 32 位值,线程 A 想要设置位 0,线程 B 想要设置位 1。
正如您所描述的,这些是读取-修改-写入操作,同步问题是“如果他们碰撞'。
您需要避免的情况是这样的:
...当正确的结果是这样的...
在某些处理器上,读取-修改写入将是三个单独的指令,因此您将需要同步。在其他情况下,它将是单个原子指令。在多个核心/CPU 系统上,它将是一条指令,但其他核心/CPU 可能能够访问,因此您再次需要同步。
用字节来做也是一样的。在某些处理器内存架构中,您只能写入 32 位内存值,因此字节更新需要像以前一样进行读取-修改-写入。
针对 X86 架构(特别是 Windows)的更新
Windows 提供了一组针对 32 位值的原子“互锁”操作,包括 逻辑或。这些可能对您避免关键部分有很大帮助。但要小心,因为正如 Raymond Chen 指出的那样,它们并不能解决所有问题 。继续阅读该文章,直到您理解为止!
In short, it's very CPU and compiler dependent.
Say you have a 32-bit value containing zero, and thread A wants to set bit 0 and thread B wants to set bit 1.
As you describe, these are read-modify-write operations, and the synchronization issue is 'what happens if they collide'.
The case you need to avoid is this:
... when the correct result is this...
On some processors, the read-modify write will be three separate instructions, so you WILL need synchronization. On others, it will be a single atomic instruction. On multiple Core/CPU systems it will be a single instruction BUT other cores/CPUs may be able to access, so again you will need synchronization.
Doing it with bytes can be the same. In some processor memory architectures, you can only write a 32-bit memory value, so byte updates require a read-modify-write as before.
Update for X86 architecture (and windows, specifically)
Windows provides a set of atomic "Interlocked" operations on 32-bit values, including Logical OR. These could be a big help to you in avoiding critical sections. but beware, because as Raymond Chen points out, they don't solve everything. Keeping reading that post until you understand it!
具体细节将取决于系统,并且可能取决于编译器。我想您可能必须一直使用 32 位整数才能摆脱您担心的影响。
The specifics will be system-dependent, and possibly compiler-dependent. I imagine you might have to go all the way to a 32-bit integer before you are free from the effects you fear.
出于您指定的原因,我相信这是真的。
在我看来,如果您的位图存储为
char[]
,并且您的架构是字节可寻址的(可以在内存中读取和写入单个字节,而无需读取整个单词),然后编译器可能会生成原子操作。即便如此,它也是完全由实现定义的,因此您不能依赖它。I believe this is true, for the reasons you specified.
The way I see it, if your bitmap is stored as a
char[]
, and if your architecture is byte addressable (it's possible to read and write an individual byte in memory, without having to read an entire word), then the compiler may generate an atomic operation. Even so, it's completely implementation-defined, so you can't rely on it.