【问题标题】:Unpredictable results with two threads calling a function两个线程调用函数的不可预测的结果
【发布时间】:2012-10-18 08:15:34
【问题描述】:

我希望有人可以帮助我解决我需要修复的 C 程序中一些不可预测的行为:

我有两个 Xenomai 实时任务(线程)等待它们从两条 CAN 总线之一接收到传入消息。
每个任务都调用一个函数 checkMessageNumber() 但是我得到了不可预知的结果。

请注意,我使用的是基于优先级的单线程系统。一个线程优先于另一个线程,但是当另一个线程获得优先权时,一个线程可能会在执行过程中部分执行。
未来有可能将硬件升级为多线程系统,但是这部分程序仍将仅限于单线程(一个 CPU 内核)。

据我了解,每个线程都会调用它自己的此函数实例,所以我不知道发生了什么。

int getMessageIndex(unsigned int msg_number)
{
    unsigned int i = 0;
    while(i < global_number_message_boxes)
    { 
        if (global_message_box[i].id == msg_number}
            return i; // matched the msg number, so return the index number
        i++;
    }
    return -1; // no match found
}

最初这个函数是高度不可预测的,并且由于消息流入并由两个任务处理(取决于消息来自哪个硬件总线),即使传入的“msg_number”匹配,该函数有时也会返回 -1 'global_message_box' 结构中的 'id'。

我可以通过将“global_number_message_boxes”设置为整数来使其更好地工作:
例如。 while(i &lt; 50)
但是,即使应该有匹配项,该函数有时仍会返回 -1。

我只读取全局变量,为什么它们会损坏?我需要了解什么?

我的想法是简化事情,因此传入的“msg_number”只是“global_message_box”中的“id”。
然后每个线程将直接写入结构,而不必检查要写入的“id”。
使用互斥锁有多重要?由于系统设计,每个线程永远不会写入结构的同一部分,所以我不确定它是否重要?

谢谢。

【问题讨论】:

  • 大概,有趣的地方是这些变量被写入的地方......
  • 消息是如何发送到线程的?是否有一个中断处理程序可以修改您的全局结构并向任务发送消息?
  • 静态无符号整数 global_number_message_boxes = 0;但是,当循环到静态整数时,我仍然会得到奇怪的行为,尽管较少。
  • 当 ID 号为 -1 时,写入 global_message_box 结构的函数会打印出错误,因为它永远不会发生。
  • @MaximSkurydin:这两个任务本质上是中断处理程序,当从各自的硬件总线接收到 CAN 消息时执行。

标签: c multithreading real-time


【解决方案1】:

这可能归结为缺少围绕全局结构的线程同步:你说这个函数只是在读取。当然可以,但是如果另一个线程调用另一个写入global_number_message_boxesglobal_message_box 的函数怎么办?在你有全局变量和多个线程访问它们的系统中,安全规则是:在每次访问时加锁。也许你使用的平台甚至支持读/写锁,所以多个线程可以同时读取,只要没有写入。

【讨论】:

  • 感谢您的回复。 global_number_message_boxes 仅在程序开始时定义。我只是想了解为什么在读取变量时会出现不可预测的行为。我会在写作部分加个锁。
  • 你应该阅读一些关于线程如何工作的资源,我不能很好地解释它。多个线程可以同时从一个内存位置读取而不会出现问题。但是,当该内存位置被写入,同时一个线程从中读取时,您会选择未定义的行为。
  • 是的,我也只是在阅读有关问题的 cmets;没有更多实际代码很难说。但是,由于 OP 说任务正在等待,并且由于您不能在中断处理程序中做很多事情,我想任务/线程等待一个信号,并且该信号是在实际的中断处理程序中设置的,因此任务不会运行中断上下文。至少这就是你在 RT 系统上做事的主要方式。
【解决方案2】:

Lock 和 Semaphores 将成为您的朋友。使用两个线程写入数据会导致很多问题。

当线程进入函数时,你将不得不阻塞其他线程并在退出时取消阻塞这些线程。这将确保线程安全操作并产生一致的结果。

【讨论】:

    猜你喜欢
    • 2016-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-26
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多