【发布时间】:2021-06-14 09:30:09
【问题描述】:
我的代码适用于具有不同布局的大型数据块。布局会决定哪些部分数据是固定的,哪些数据是不固定的。一旦数据被固定在一个块中,它通常就不会再改变了。所以所有的代码读取数据总是会看到相同的数据。
但是,其他服务可以在这些块中进行更改,只要它们确定没有代码会读取块的那部分。为了简化代码,包含更改的块将从一个服务发送到另一个服务,而不管块的布局如何。然后接收服务将覆盖整个块,包括未更改的数据。让我用一个例子来说明这一点:
假设我们有以下数据块:
| 57 | 23 | 98 | 17 | 25 | 00 | 00 | 00 | 00 | 00 |
|---|
假设前 5 个值是“固定的”。我们服务中的代码只会读取前 5 个值,而不会读取接下来的 5 个值。由于我们的架构设计,我们可以保证这一点。接下来的 5 个值实际上没有意义,所以我在表中填了零来说明这一点。
现在另一个服务确定接下来的 5 个值,将完整的块发送到我们的服务,我们只需用新数据覆盖完整的块。由于前 5 个值是“固定的”,它们保持不变,但传输和覆盖块的代码不知道块的布局,所以它唯一能做的就是覆盖整个块。结果如下:
| 57 | 23 | 98 | 17 | 25 | 08 | 33 | 42 | 71 | 85 |
|---|
如前所述,前 5 个值没有改变,尽管它们被传输逻辑覆盖。
问题是:这是一场数据竞赛吗?如果其他线程可以同时读取数据,是否允许用完全相同的值覆盖内存地址?
【问题讨论】:
-
我喜欢你的问题,认为它很清楚,不知道我是否可以回答.....但是,请记住,StackOverflow 的用户喜欢查看代码。也许您可以模拟一些代码来说明您描述的活动。使用慷慨的评论来表达隐含或特殊之处。
-
我假设我们正在查看普通内存。没有像内存映射外设或 DMA 处理的区域......请确认或详细说明。
-
@Yunnosch 即使有这样的影响——因为源和目标无论如何都是相同的,即使是对值的破坏读取不能导致数据不一致,所以除非标准规定这是UB,我认为没有问题。然而,changed 部分需要被保护。但是,如果不知道哪个部分需要保护,应对代码应该如何做到这一点?如果它知道,它可以简单地跳过不需要的部分......
-
@Aconcagua 你似乎生活/工作在一个比我更受保护的世界里。如果您从未遇到硬件正在写入一个字节/寄存器会更改从另一个字节读取的值 - 然后认为自己很高兴。我在这里说的是非常奇怪的硬件。并且只要求确认,因为我了解到偏执狂对于(嵌入式)程序员来说是一种健康的心态。
-
@Yunnosch 好点 - 默默地假设这是普通 RAM,没有注意到映射到内存地址空间的功能寄存器也可能在这里涉及......
标签: c++ windows multithreading data-race