You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Xenomai中观测竞态条件?

如何在Xenomai中观测竞态条件?

嘿,我来帮你搞定这个Xenomai里观测竞态条件的问题!首先得说,竞态条件本身是概率性的,有时候没触发不是你代码错了,而是没给它足够的“机会”显现出来。我给你拆解下怎么调整代码,让竞态更容易被观测到:

第一步:补全并改造你的increment函数

原来的自增操作counter++其实是读内存→加1→写内存三步,正常情况下这三步太快,线程切换很难刚好卡在中间,所以竞态很难出现。我们可以故意放大这个“脆弱窗口”,比如在读写之间加个小延迟:

#include <alchemy/task.h>
#include <alchemy/printf.h> // 用Xenomai的rt_printf更安全,避免实时任务里用printf的问题
#include <unistd.h>
#include <stdio.h>

RT_TASK t1, t2, t3, t4, t5, t6, t7, t8, t9;
volatile int counter = 0; // volatile必须保留,防止编译器优化

void increment(void *arg) {
    int temp = counter;
    // 打印当前任务读到的counter值,方便观测
    rt_printf("任务[%s]读到counter: %d\n", rt_task_self()->name, temp);
    // 用Xenomai的延迟函数放大竞态窗口,单位是纳秒(这里是1毫秒)
    rt_task_sleep(1000000);
    counter = temp + 1;
    rt_printf("任务[%s]写回counter: %d\n", rt_task_self()->name, counter);
}

第二步:补全main函数,保证任务优先级一致

要让竞态容易出现,得让所有任务的优先级相同——这样Xenomai的调度器会轮询调度它们,不会出现高优先级任务霸占CPU的情况。补全任务创建和启动的代码:

int main() {
    // 创建9个任务,优先级都设为99(相同优先级),栈大小用默认0即可
    rt_task_create(&t1, "task1", 0, 99, 0);
    rt_task_create(&t2, "task2", 0, 99, 0);
    rt_task_create(&t3, "task3", 0, 99, 0);
    rt_task_create(&t4, "task4", 0, 99, 0);
    rt_task_create(&t5, "task5", 0, 99, 0);
    rt_task_create(&t6, "task6", 0, 99, 0);
    rt_task_create(&t7, "task7", 0, 99, 0);
    rt_task_create(&t8, "task8", 0, 99, 0);
    rt_task_create(&t9, "task9", 0, 99, 0);

    // 启动所有任务,执行increment函数
    rt_task_start(&t1, &increment, NULL);
    rt_task_start(&t2, &increment, NULL);
    rt_task_start(&t3, &increment, NULL);
    rt_task_start(&t4, &increment, NULL);
    rt_task_start(&t5, &increment, NULL);
    rt_task_start(&t6, &increment, NULL);
    rt_task_start(&t7, &increment, NULL);
    rt_task_start(&t8, &increment, NULL);
    rt_task_start(&t9, &increment, NULL);

    // 等待所有任务执行完成(这里延时5秒足够)
    sleep(5);

    // 打印最终结果,正常预期是9,有竞态的话会小于9
    printf("最终counter值: %d\n", counter);

    // 清理任务资源
    rt_task_delete(&t1);
    rt_task_delete(&t2);
    rt_task_delete(&t3);
    rt_task_delete(&t4);
    rt_task_delete(&t5);
    rt_task_delete(&t6);
    rt_task_delete(&t7);
    rt_task_delete(&t8);
    rt_task_delete(&t9);

    return 0;
}

第三步:观测竞态的方法

  1. 看最终结果:如果运行后最终counter值小于9(比如7、8),说明竞态已经发生了——多个线程读到了同一个初始值,最后写回时互相覆盖,导致counter没有按预期增加。
  2. 看实时打印:通过rt_printf的输出,你会看到类似这样的场景:比如task1和task2都读到了counter=0,然后延迟1毫秒后,都写回了1,这时候counter只增加了1,而不是2——这就是竞态条件的直观表现!

小技巧提高竞态出现概率

  • 如果一次运行没出现,多跑几次(毕竟竞态是概率性的);
  • 增加线程数量(比如加到20个),或者把延迟时间调长一点;
  • 不要给任务设置不同的优先级,否则高优先级任务会先跑完所有步骤,低优先级任务没机会插进来。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 13:48:07