确实需要使用互斥锁吗?

时间:2011-10-05 20:06:03

标签: c++ multithreading mutex

简单版:在C ++程序中,我使用两个不同的线程来处理一些整数变量。但我确信一个人总是在写一些价值,而另一个人只是在读它。在读/写数据时我还需要使用互斥锁吗?

现在详细说明:主要思想是第一个线程生成一些信息并将它们保存到数组中,第二个线程从该数组中读取数据并处理它们。这个数组代表一个队列。意思是我有两个索引值指向队列中的第一个和最后一个项目。现在我想知道每当我正在读取或写入值时是否必须锁定这两个索引值,还是可以在没有锁定的情况下检查它们?请注意,生成器线程是queue_back唯一的线程更改索引,处理器线程具有更改queue_front的独占权限。

如果进行任何更改我正在为基于Linux的系统开发,代码是使用gcc编译的。

PS:在一些使用线程的代码中,我看到不同线程之间共享变量的关键字volatile,我是否也需要使用它?

6 个答案:

答案 0 :(得分:3)

读取和写入都不是原子的,您需要使用某种同步机制来同步它。

此外,您必须将共享整数标记为volatile,否则优化程序可能会认为该变量永远不会在您的某个线程中更新。

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);

答案 1 :(得分:1)

是的,您需要同步访问变量,使用互斥锁,临界区,互锁访问等,以确保读写线程在写入线程仍在保存时不会读取不完整的字节。这对于多核/ CPU系统尤为重要,因为两个线程可以并行地真正访问变量。

答案 2 :(得分:1)

读取和写入正确对齐的数据不大于机器字(通常是int解析的)在大多数主要体系结构上都是原子的。那意味着每个架构。​​

这意味着不,您不能只阅读headtail并期望数据一致。但是,如果例如sizeof(int)碰巧是4并且sizeof(short)碰巧是2,如果你不关心“不是主流”平台,你可以做一些联合技巧并在没有原子的情况下逃脱操作或互斥。

如果您希望代码可移植,则无法正确锁定或进行原子比较/交换。

关于volatile,此 为Microsoft Visual C ++插入内存屏障(作为特定于编译器的诡辩),但标准保证任何特殊内容除此之外,编译器不会优化变量。就此而言,制作volatile并没有多大帮助,它绝不保证线程安全。

答案 3 :(得分:1)

  

读取/写入数据时是否还需要使用互斥锁?

是的,你需要一把锁。您可能对称为读/写锁的更具体的实现感兴趣。

您还可以使用原子和/或记忆障碍。使用这些将需要更好地了解您的目标体系结构。重现多线程错误可能非常困难,这些替代方案应被视为可能无法移植的优化。

  

我看到不同线程之间共享变量的关键字volatile,我是否也需要使用它?

让人惊讶。没有!这不是C ++中多线程读写的安全或可移植解决方案。使用原子,锁,复制,不可变和纯实现(等等)。

volatile的解释因平台和/或编译器而异,并且没有指定在C或C ++中以任何特定方式操作以进行多线程读写(有一个古老的错误传说,它可以是可靠地用作原子读/写)。我曾经在多线程C ++程序中测试volatile的有效性(在带有apple的gcc的intel-mac上)。我不会提供结果,因为它的工作足够,有些人可能会考虑使用它,虽然他们应该不是因为“几乎”不够好。

并限定volatile的使用:它存在于我的(大型,严格编写,多线程识别)代码库中,其唯一目的是与平台相关的原子API接口。并且完全诚实:早期还有其他一些用途,但它们可以而且应该被删除。

答案 4 :(得分:0)

是的,您需要使用某种同步机制(如互斥锁)来保护生成器和读取器线程中的队列索引。

HTH

答案 5 :(得分:0)

如果您真的只是共享一个整数,那么std::atomic<int>听起来就像<atomic>标题中使用的正确类型一样。 (如果你有一个旧的编译器,也应该有Boost或TR1版本。)这确保了原子读写。据我所知,不需要volatile限定符。

相关问题