【问题标题】:Multiple threads update global variables periodically while third thread waiting to read多个线程定期更新全局变量,而第三个线程等待读取
【发布时间】:2012-04-18 13:02:22
【问题描述】:

我有两个线程 A,B 定期更新两个全局传感器读取变量,它们执行相同的例程。第三个线程 C 将在这些值更新后立即对它们进行一些计算。我设置了一些条件变量,当 A 和 B 都更新全局变量时,C 将立即读取。我担心线程 C 错过了一些传感器读数,因为它使用 while 循环的轮询安排在新的 A、B 更新之后。我不确定我的担心是否必要,因为我是 pthread 的新手。 我的开发环境是嵌入式linux板,目前正在学习pthread。 有没有比为每个全局变量设置两个条件变量更好的方法。

【问题讨论】:

  • 以什么方式更好?条件变量有什么问题?你有代码复杂性的问题吗?表现?正确性的保证?有实际的争执吗?或者这种访问只是偶尔的,所以重要的是正确性? (如果是这样,为什么不直接使用互斥锁?)
  • C 不能错过更新重要吗?例如,传感器 A 的读数在 C 开始使用它之前更新两次是否可以(因此 C 只关心最近的读数)还是不可接受?如果是后者,那么可能需要一个可以容纳多个读取的队列,或者您可能需要阻塞生产者线程(A 或 B),直到 C 开始使用更新。

标签: linux multithreading thread-safety pthreads posix


【解决方案1】:

我会使用一个互斥体、一个条件变量和一个谓词整数生成计数器(只是一个初始化为零的常规整数)。逻辑是这样的:

要更新值:锁定互斥体。更新值。增加谓词整数。广播条件变量。释放互斥锁。

读取当前值:锁定互斥体。复制谓词整数生成计数器的值。读取值。释放互斥锁。

检查新值:锁定互斥体。检查谓词整数与您上次读取值时复制的值。如果不同,就有新的价值。释放互斥锁。

等待新值:锁定互斥体。虽然谓词整数仍然保留上次读取值时所保留的值,但阻止释放互斥锁的条件变量。为下一次等待复制新的谓词整数。注意新值。释放互斥锁。

【讨论】:

  • 谓词整数风险溢出,我设置了flags,读完后再转。
  • 溢出是无害的,因为值仍然会改变。但如果你真的很偏执,一旦超过 10 亿,你可以将其切换回零。
  • 如果我正确理解了这个问题,你会想要两个值中的每一个都有一个生成计数器(或标志),以便 C 可以确定更新了哪个读数(或两者)。
  • 你可能会。如果您希望线程能够等待特定变量更新,您可能需要两个条件变量。这些都是您在实施过程中可以做出的选择。
【解决方案2】:

你的另一个选择是一个普通的互斥体。

pthread_mutex_t lockX = PTHREAD_MUTEX_INITIALIZER;

[...]

pthread_mutex_lock(lockX);
// do things with shared variable
pthread_mutex_unlock(lockX);

这适用于读取和写入,因为即使使用单个 int,线程 A 也可以读取 一半 一个值,然后线程 B 写入同一个变量,线程 B 继续读取另一半,产生了一个从未存在过的“价值”。

你没有在线程中使用全局变量,顺便说一句。您可以将包含任何内容的结构指针传递给线程函数。

【讨论】:

  • 当你说“线程A读取一半值,然后线程B写入同一个变量,线程B继续读取另一半,产生一个“值”时,你能启发我吗?从未存在过。”
  • 这正是他所说的。如果没有适当的同步,读取和写入可能会重叠,导致读取一半的旧值和一半的新值。假设一个变量包含值“93”,而您正在向它写入“31”。如果我在你写作的同时阅读,我可能会读“9”然后你写“31”然后我读“1”,所以我认为值是“91”,它 从来没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 2018-08-02
  • 1970-01-01
  • 1970-01-01
  • 2015-08-23
  • 1970-01-01
  • 2020-10-04
相关资源
最近更新 更多