当前位置:  开发笔记 > 编程语言 > 正文

多线程的偏执狂

如何解决《多线程的偏执狂》经验,为你挑选了4个好方法。

这是一个复杂的问题,请在回答之前仔细考虑.

考虑这种情况.两个线程(读取器和写入器)访问单个全局int.这样安全吗?通常,我会毫不犹豫地回答,是的!

然而,在我看来,Herb Sutter并不这么认为.在他关于有效并发的文章中,他讨论了一个有缺陷的无锁队列和纠正的版本.

在第一篇文章的末尾和第二篇文章的开头,他讨论了很少考虑的变量特征,即写入顺序.Int是原子的,很好,但是int不一定是有序的,它可以破坏任何无锁算法,包括我上面的场景.我完全同意,保证现有和未来所有平台上正确的多线程行为的唯一方法是使用原子(AKA内存屏障)或互斥.

我的问题; 在实际硬件上写的重写是否有问题?还是多线程的偏执狂只是迂腐?
那么经典的单处理器系统呢?
那些更简单的RISC处理器如嵌入式电源?

澄清:我对Sutter先生所说的硬件(处理器/缓存)重新排序变量写入更感兴趣.我可以阻止优化器使用编译器开关破坏代码或手动检查汇编后编译.但是,我想知道硬件是否仍然可以在实践中搞乱代码.



1> Jason Cohen..:

你对检查装配的想法不够好; 重新排序可以在硬件级别进行.

要回答你的问题"这对读硬件来说一个问题:" 是的! 事实上,我自己遇到了这个问题.

可以解决单处理器系统或其他特殊情况下的问题吗?我认为"不",因为从现在起五年后你可能需要在多核上运行,然后找到所有这些位置将是棘手的(不可能?).

一个例外:为嵌入式硬件应用程序设计的软件确实可以完全控制硬件.事实上,在例如ARM处理器的情况下,我已经"欺骗"了这种情况.



2> Eclipse..:

是的 - 使用内存屏障来防止需要时的指令重新排序.在一些C++编译器中,volatile关键字已经扩展为每次读写都插入了隐式内存屏障 - 但这不是一个可移植的解决方案.(与Interlocked*win32 API类似).Vista甚至添加了一些新的更细粒度的Interlocked API,它允许您指定读或写语义.

不幸的是,C++有一个松散的内存模型,任何类似的代码在某种程度上都是不可移植的,你必须为不同的平台编写不同的版本.



3> Chris Jester..:

就像你说的那样,由于在缓存或处理器级别进行了重新排序,你实际上确实需要某种内存屏障来确保正确的同步,特别是对于多处理器(特别是在非x86平台上).(我相信单处理器系统没有这些问题,但是不要引用我的话 - 我当然更倾向于安全地进行同步访问.)



4> Rob Walker..:

我们遇到了这个问题,尽管在Itanium处理器上,指令重新排序比x86/x64更具攻击性.

解决方法是使用Interlocked指令,因为当时(当时)没有办法告诉编译器只是简单但是在赋值后写入屏障.

我们真的需要语言扩展来干净利落地处理这个问题.对于你试图从一段代码中尽可能多地提高性能的情况来说,使用volatile(如果编译器支持的话)太粗糙了.

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有