两个线程的公共资源——同步够不够?

Posted

技术标签:

【中文标题】两个线程的公共资源——同步够不够?【英文标题】:Common resource of two threads - synchronization enough? 【发布时间】:2017-06-30 11:10:44 【问题描述】:

假设我有一些课程,无论它可能具有什么样的性质。我想在线程之间共享这个类的一个对象。过去,我认为mutex(虽然它可能不是最有效的方式)足以确保一切正常。

现在,我已经阅读了一些关于 std::atomic 的内容,即使对于简单的布尔引用也是必要的:Do I have to use atomic<bool> for "exit" bool variable?

虽然我理解为什么 bool 应该是原子的,但我不明白简单的互斥锁如何防止以下问题:

其次,当两个线程运行在不同的内核上时,它们有独立的缓存;写入值会将其存储在缓存中,但不会更新其他缓存,因此一个线程可能看不到另一个线程写入的值。

互斥锁不仅仅是一种确保其他线程无法锁定互斥锁的机制吗?但在互斥体区域内,我可能会玩弄一大堆变量。编译器可能不知道涉及哪些变量。

因此,目前对我来说,简单地在所有包含共享资源的区域周围放置一个基于互斥锁的锁似乎还不够。会不会因为线程缓存不会更新,所以两个线程有​​不同版本的资源?

【问题讨论】:

this 会回答你的问题吗? @Default 不完全。它说在 C++0x 之前没有任何保证,但它没有详细说明 C++0x 如何提供帮助。 manni66 的回答更有见地 还有内存栅栏,它被CPU用作一种序列点来同步内存。所以你有一个机制来同步所有内核和线程的内存和缓存以及一个同步原语,互斥锁。有关说明,请参阅 ***.com/questions/7280119。 【参考方案1】:

C++ 存储模型保证一个线程中对象的更改对其他线程可见,如果它们受到互斥锁的保护。详情请见http://en.cppreference.com/w/cpp/language/memory_model。

【讨论】:

那么,有人会跟踪互斥区域内的变量吗?我的意思是,我猜这必须在运行时进行,所以它不会花费很多时间吗? @IceFire 是的,它很贵。最好避免共享数据。 @IceFire - 并没有真正跟踪,而是导致系统范围内的缓存“刷新”(CPU 内存缓存等) - 即现在可以看到任何更改,因为一切都是现在很脏,需要刷新。 @RichardCritten 这似乎更麻烦。当我使用互斥锁时,整个缓存都会变脏?这实际上会禁用缓存。而且如果仅限于互斥体区域内的变量,一些跟踪似乎仍然是必要的,否则运行时如何知道要取消缓存哪些变量? @manni66 我已经阅读了 memory_model 文章,但它没有说明缓存副本。它只是说互斥体清楚地设置了内存顺序,因此没有数据竞争。但是没有说明或解释数据竞争的原因,也没有说明互斥锁如何解决它们。您有更详细的来源还是可以添加更详细的说明?

以上是关于两个线程的公共资源——同步够不够?的主要内容,如果未能解决你的问题,请参考以下文章

多线程之线程同步(互斥锁信号量条件变量和读写锁​)

多线程之线程同步(互斥锁信号量条件变量和读写锁​)

线程同步的方式和机制

互斥锁和信号量

进程同步概念简介 多线程上篇

C++多线程同步技巧--- 互斥体