这是我的第一个多线程实现,所以这可能是初学者的错误。线程处理每隔一行像素的渲染(因此所有渲染都在每个线程内处理)。如果线程分别渲染屏幕的上部和下部,问题仍然存在。
两个线程从相同的变量读取,这会导致任何问题吗?据我所知,只有写作会导致并发问题......
调用相同的函数会导致任何并发问题吗?再说一次,据我所知,这应该不是问题......
两个线程写入同一变量的唯一时间是保存计算的像素颜色。它存储在一个数组中,但它们永远不会写入该数组中的相同索引。这会导致问题吗?
Multi-threaded rendered image (垃圾邮件预防阻止我直接发布图片..)
聚苯乙烯。我在两种情况下都使用完全相同的实现,唯一的区别是为渲染创建的单线程和两线程。
答案 0 :(得分:6)
两个线程从相同的变量读取,这会导致任何问题吗?据我所知,只有写作会导致并发问题......
这应该没问题。显然,只要数据在两个线程开始读取之前被初始化,并且在两个线程完成之后就被销毁。
调用相同的函数会导致任何并发问题吗?再说一次,据我所知,这应该不是问题......
是和否。没有代码就太难说了。这个功能有什么作用?它是否依赖于共享状态(例如static
变量,全局变量,单例......)?如果是的话,那肯定是个问题。如果从来没有任何共享状态,那么你没事。
两个线程写入同一变量的唯一时间是保存计算的像素颜色。它存储在一个数组中,但它们永远不会写入该数组中的相同索引。这会导致问题吗?
有时可能。一阵什么?如果sizeof(element) == sizeof(void*)
可能是安全的,但C ++标准在多线程上是静音的,因此它不会强迫您的编译器强制您的硬件使其安全。您的平台可能会在这里咬你(例如64位机器和一个写32位的线程可能会覆盖相邻的32位值),但这不是一种罕见的模式。通常你最好使用同步来确定。
您可以通过以下几种方式解决此问题:
我的答案中缺乏承诺是使多线程编程变得困难的原因:P
例如,从 Intel® 64 and IA-32 Architectures Software Developer's Manuals开始,描述了不同平台如何保持不同的原子性水平:
7.1.1保证原子操作
Intel486处理器(以及更新版本 处理器,因为)保证 以下基本内存操作会 总是以原子方式进行:
- 读取或写入字节
- 读取或写入在16位边界上对齐的字
- 读取或写入在32位边界上对齐的双字
奔腾处理器(以及更新版本 处理器,因为)保证 跟随额外的内存操作 将始终以原子方式进行:
- 读取或写入在64位边界上对齐的四字
- 16位访问适合32位数据总线的未缓存内存位置
P6系列处理器(以及更新版本 处理器以来)保证 以下额外的内存操作 将始终以原子方式进行:
- 对缓存线内的高速缓存行的16位,32位和64位未对齐访问
访问可缓存的内存 分割总线宽度,缓存线, 和页面边界不保证 英特尔酷睿2双核处理器, Intel Atom,Intel Core Duo,Pentium M, Pentium 4,Intel Xeon,P6系列, 奔腾和Intel486处理器。该 英特尔酷睿2双核,英特尔凌动,英特尔 Core Duo,Pentium M,Pentium 4,Intel Xeon和P6系列处理器提供 允许的总线控制信号 外部存储器子系统 拆分访问原子;然而, 非对齐数据访问将 严重影响了业绩 处理器,应该避免。
答案 1 :(得分:1)
我已经解决了这个问题,我是通过像Stephen建议的那样单独为每个线程建立数据来做到的(这些元素不是void * size)。谢谢你非常详细的答案!