线程安全编程

Kam*_*Kam 7 c++ concurrency multithreading thread-safety

我一直听说线程安全.究竟是什么以及如何以及在何处学习编写线程安全代码?

另外,假设我有2个线程,一个写入结构,另一个从中读取.这有什么危险吗?有什么我应该寻找的吗?我不认为这是一个问题.两个线程都不会(很不能)在同一时间访问结构.

此外,有人可以告诉我如何在这个例子中:https://stackoverflow.com/a/5125493/1248779我们在并发问题上做得更好.我不明白.

Joe*_*Joe 7

这是一个非常深刻的话题.心脏线程通常是通过同时使用多个核心来使事情变得更快; 或者当你没有很好的方法将操作与'主'线程交错时,在后台进行长时间的操作.后者在UI编程中非常常见.

你的场景是经典的麻烦点之一,也是最早遇到的人之一.拥有一个成员真正独立的结构是很少见的.想要修改结构中的多个值以保持一致性是很常见的.在没有任何预防措施的情况下,很可能修改第一个值,然后让另一个线程读取结构并在写入第二个值之前对其进行操作.

简单的例子是2d图形的'点'结构.您想将点从[2,2]移到[5,6].如果你有一个不同的线程画一条线到那一点你可能很容易画到[5,2].

这真的是冰山一角.有很多好书,但学习这个空间通常是这样的:

  1. 哦,我只是从那个处于不一致状态的东西中读出来的.
  2. 哦,我只是从2个线程修改了这个东西,现在它是垃圾.
  3. 好极了!我了解了锁
  4. 哇,我有很多锁,当我有很多锁定嵌套代码时,一切似乎都会挂起.
  5. 人力资源管理.我需要在飞行中停止这种锁定,我似乎错过了很多地方; 所以我应该将它们封装在数据结构中.
  6. 那个数据结构很棒,但是现在我似乎一直在锁定,而且我的代码和单个线程一样慢.
  7. 条件变量很奇怪
  8. 这很快,因为我对如何锁定东西很聪明.人力资源管理.有时数据会破坏.
  9. 哇.... InterlockedWhatDidYouSay?
  10. 嘿,看起来没锁,我做这个叫旋转锁的东西.
  11. 条件变量.嗯...我明白了.
  12. 你知道吗,我只是开始考虑如何以完全独立的方式操作这些东西,管理我的操作,以及尽可能少的跨线程依赖...

显然,这不仅仅是条件变量.但是有很多问题可以通过线程解决,可能几乎有很多方法可以解决,甚至更多的方法可以解决问题.


djn*_*jna 4

线程安全是“并发编程”总标题下的一大组问题的一个方面。我建议阅读该主题。

您认为两个线程无法同时访问该结构的假设是不好的。第一:今天我们有多核机器,因此两个线程可以同时运行。其次:即使在单核机器上,分配给任何其他线程的时间片也是不可预测的。您必须预测“其他”线程可能正在处理的任意时间。请参阅下面我的“机会之窗”示例。

线程安全的概念正是为了回答“这有什么危险吗”这个问题。关键问题是,在一个线程中运行的代码是否可能获得某些数据的不一致视图,这种不一致的发生是因为它运行时另一个线程正在更改数据。

在您的示例中,一个线程正在读取结构,同时另一个线程正在写入。假设有两个相关字段:

  { foreground: red; background: black }
Run Code Online (Sandbox Code Playgroud)

作者正在改变这些

   foreground = black;
            <=== window of opportunity
   background = red;
Run Code Online (Sandbox Code Playgroud)

如果读者恰好在那个机会窗口读取值,那么它会看到一个“无意义”的组合

  { foreground: black; background: black }
Run Code Online (Sandbox Code Playgroud)

这种模式的本质是,在我们进行更改的短时间内,系统会变得不一致,读者不应该使用这些值。一旦我们完成更改,就可以安全地再次阅读。

因此,我们使用 Stefan 提到的 CriticalSection API 来防止线程看到不一致的状态。