【问题标题】:What are the problems/issues that I can face when working with threads? [closed]使用线程时我会遇到哪些问题/问题? [关闭]
【发布时间】:2017-07-26 17:17:54
【问题描述】:

我了解到在使用线程时可能会遇到的以下问题:

  • 当你将一个值写入内存中的变量时,该值不一定会写入内存位置(该值可以写入缓存),因此如果另一个线程正在读取该变量,它不会读取其他线程刚刚写入的值。

  • 1234563您的线程正在尝试读取它,它不会读取另一个线程刚刚写入的值。 1234563一个线程必须等待另一个线程完成计算)。
  • 编译器和/或 CPU 可能会乱序执行您的程序指令。

  • 您可能会出现死锁(如果每个线程在继续之前都在等待另一个线程发出信号)。

在使用线程时我还会遇到其他问题吗?

【问题讨论】:

  • 谷歌关于 RaceConditions
  • 函数需要可重入。 C 标准库相当安全,strtok 是一个明显的例外。

标签: c multithreading winapi


【解决方案1】:

将值写入内存中的变量时,该值不一定会写入内存位置(可以将值写入缓存)

您在错误的抽象级别上考虑它。您说的是真的,但您使用的编程语言工具链的开发人员最感兴趣的是。从应用程序开发人员的角度来看,一个线程写入内存的值不会立即对其他线程可见。

编译器和/或 CPU 可能会乱序执行您的程序指令

不如说,当一个线程将多个值按顺序写入内存时,其他线程不一定会看到新值以相同的顺序出现。

在任何单个线程中,编译器和 CPU 都必须确保一切看起来都以程序顺序发生。

...有些任务需要是“原子的”,例如,如果两个线程正在对一个变量进行计算,则不能让这两个线程同时进行计算

再次正确,但这还不足以提供有用的信息。您需要知道何时为什么两个不同的线程可以或不能同时进行计算。

关键概念是不变量。不变量是始终假定为真的任何条件。例如,如果你正在实现一个链表结构,一个不变量是每个“next”指针要么指向列表的成员,要么指向 NULL。如果您正在实现一个链接节点环,那么一个不变量表示,如果您遵循“下一个”指针链足够远,它将始终带您回到起点。

通常情况下,如果不临时破坏不变量,就无法执行某些操作。例如,如果不暂时将结构置于无效状态,您可能无法将某些内容插入到某些数据结构中。

您说过,“有些任务需要是‘原子的’”。更好的说法是,有些任务需要互斥(互斥体),以防止一个线程看到因其他线程的操作而处于暂时中断状态的不变量。

【讨论】:

  • 我发现我可以在 WinAPI 中使用临界区来强制互斥。但是如何做到以下几点:1)确保一个线程将一个值写入变量时,该值直接写入内存(即其他线程可以看到),2)如何确保一组指令我指定的将按照我编写它们的顺序执行?
  • @Christopher, Re (1) 答案取决于您正在使用的系统的内存模型。如果您使用 Java,我可以准确地告诉您在哪里可以找到 Java 内存模型的正式描述。我不太了解 C 和 C++,但是大多数 系统至少会保证这么多:如果线程 A 在解锁某个锁之前将某些内容写入内存,然后线程 B 会锁定 同样的锁,线程B就能看到线程A写了什么。
  • Re (2),你不能——至少,不能不诉诸特定于你的编译器/版本、操作系统/版本和/或处理器的技巧。在任何单个线程中,都没有关系。任何单个线程的执行将始终与您编写的代码具有相同的效果。在线程之间,必须使用互斥锁或其他同步方法,以确保线程只能看到处于有意义、一致状态的共享数据结构。
猜你喜欢
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多