简单版:在C++程序中,我使用两个不同的线程来处理某个整数变量。但我确信其中一个总是在其中写入一些值,而另一个只是在读取这些值。在读/写数据时,我还需要使用互斥锁吗?
现在详细说明:主要思想是第一个线程生成一些信息并将它们保存到一个数组中,第二个线程从该数组中读取数据并处理它们。该数组表示一个队列。这意味着我有两个索引值,分别指向队列中的第一项和最后一项。现在我在想,当我读或写值时,是否必须锁定这两个索引值,或者可以不加锁地检查它们?请注意,生成器线程是唯一更改queue_back索引的线程,处理器线程具有更改queue_front的独占权限。
如果有任何变化,我正在为一个基于linux的系统开发,代码是用gcc编译的。
PS:在一些使用线程的代码中,我看到了在不同线程之间共享变量的关键字volatile,我也需要使用它吗?
发布于 2011-10-06 04:09:56
不,读和写不是原子的,你需要使用一些同步机制来同步它。
此外,您必须将共享整数标记为易失性,否则优化器可能会认为变量永远不会在您的某个线程中更新。
gcc允许您对int、long和long long(以及它们的无符号对等项)执行原子操作。
查找以下函数:
type __sync_fetch_and_add (type *ptr, type value);
type __sync_fetch_and_sub (type *ptr, type value);
type __sync_fetch_and_or (type *ptr, type value);
type __sync_fetch_and_and (type *ptr, type value);
type __sync_fetch_and_xor (type *ptr, type value);
type __sync_fetch_and_nand (type *ptr, type value);发布于 2011-10-06 04:25:38
读/写数据时还需要使用互斥锁吗?
是的,你需要一把锁。您可能对称为读/写锁的更具体的实现感兴趣。
您还可以使用原子和/或内存屏障。使用这些将需要更好地理解您的目标架构。重现多线程bug可能非常困难,这些替代方案应该被认为是一种可能不可移植的优化。
我见过在不同线程之间共享变量的关键字不稳定,我也需要使用它吗?
啊呀。不是的!对于C++中的多线程读写来说,这不是一个安全或可移植的解决方案。使用原子、锁、复制、不可变和纯实现(等等)而不是。
对volatile的解释可以根据平台和/或编译器的不同而有所不同,并且在C或C++中没有指定以任何特定的方式操作多线程读写(有一个古老的错误传说,即它可以可靠地用作原子读/写)。我曾经在一个多线程的C++程序中测试过volatile的有效性(在一台英特尔-mac和苹果公司的gcc的电脑上)。我不会提供结果,因为它工作得足够好,一些人可能会考虑使用它,尽管他们不应该考虑使用它,因为“几乎”还不够好。
为了限定volatile的使用:它存在于我的(大型的、严格编写的、支持多线程的)代码库中,唯一的目的是与平台相关的atomics接口。坦率地说:早些时候还有一些其他用途,但它们可以而且应该被删除。
发布于 2011-10-06 04:10:50
是的,您需要通过互斥、临界区、互锁访问等同步对变量的访问,以确保读取线程不会读取不完整的字节,而写入线程仍在保存它们。这在多核/CPU系统中尤其重要,在这种系统中,两个线程可以真正并行地访问变量。
https://stackoverflow.com/questions/7667077
复制相似问题