多线程C / C ++变量无缓存(Linux)

时间:2011-08-23 18:34:05

标签: c linux multithreading synchronization

我使用2个pthreads,其中一个线程“通知”另一个事件,并且有一个变量(正常整数),由第二个线程设置。

这有效,但我的问题是,第一个(阅读)线程是否可能不会立即看到更新,这意味着缓存不会直接更新?如果是这样,有没有办法防止这种行为,例如喜欢java中的volatile关键字吗?

(事件发生的频率大约在微秒范围内,因此需要或多或少立即更新)。

/ edit:第二个问题:是否可以强制将变量保存在线程1所在的核心的缓存中,因为这个变量一直在读取它。 ?

4 个答案:

答案 0 :(得分:2)

听起来好像你应该使用pthread条件变量作为你的信号机制。这会解决您描述的所有问题。

答案 1 :(得分:2)

其他处理器可能无法立即看到它,但由于缓存一致性。可见性的最大问题是由于处理器的out-of-order execution方案或者由于编译器在优化时重新排序指令。

为了避免这两个问题,您必须使用memory barriers。我相信大多数pthread原语是自然的内存障碍,这意味着你不应该期望加载或存储被移动到锁定和解锁调用形成的边界之外。 volatile关键字也可用于禁用某些类型的编译器优化,这些优化在执行无锁算法时非常有用,但它不能替代内存障碍。

话虽如此,我建议您不要手动执行此操作,并且存在与无锁算法相关的相当多的陷阱。把这些令人头疼的事情留给图书馆的写作者应该让你更快乐(除非你像我一样,你喜欢头痛:))。所以我最后的推荐是忽略我所说的一切,并使用vromanov或David Heffman所建议的内容。

答案 2 :(得分:2)

将信号从一个线程传递到另一个线程的最合适方法应该是使用运行时库的信号机制,例如互斥锁,条件变量,信号量等。

如果这些开销太高,我首先想到的是程序结构有问题。如果事实证明这确实是瓶颈,重组程序是不合适的,那么我会使用编译器或合适的库提供的原子操作。

使用普通int变量,甚至是volatile - 合格的变量容易出错,除非编译器保证它们具有适当的语义。例如MSVC对volatile变量的普通加载和存储的原子性和排序约束做出特别保证,但gcc没有。

答案 3 :(得分:1)

使用原子变量的更好方法。对于示例,您可以使用libatomic。 volatile关键字不够用。