首页 > 其他分享 >状态机轮转的偶发性bug举例与修复策略

状态机轮转的偶发性bug举例与修复策略

时间:2025-01-08 14:32:59浏览次数:3  
标签:task taskRepository void TaskState 偶发性 状态机 public taskId bug

// 场景1:状态检查和更新不是原子操作,导致竞态条件
public class RaceConditionBug {
    private volatile TaskState state = TaskState.PENDING;
    
    // 问题代码
    public void processTaskWithBug(String taskId) {
        // 检查和更新之间可能有其他线程修改状态
        if (state == TaskState.PENDING) {
            // 这里可能被其他线程中断
            Thread.sleep(100); // 模拟一些处理
            state = TaskState.RUNNING; // 状态可能已经被其他线程改变
        }
    }
    
    // 修复方案:使用同步块
    public void processTaskFixed(String taskId) {
        synchronized (this) {
            if (state == TaskState.PENDING) {
                state = TaskState.RUNNING;
            }
        }
    }
}

// 场景2:事件处理顺序依赖导致的问题
public class EventOrderingBug {
    private BlockingQueue<StateEvent> eventQueue = new LinkedBlockingQueue<>();
    private volatile TaskState state = TaskState.PENDING;
    
    // 问题代码
    public void handleEventsWithBug() {
        executor.submit(() -> {
            StateEvent event1 = eventQueue.take();
            processEvent(event1); // 处理第一个事件
        });
        
        executor.submit(() -> {
            StateEvent event2 = eventQueue.take();
            processEvent(event2); // 可能在event1之前处理
        });
    }
    
    // 修复方案:使用单线程处理保证顺序
    private final ExecutorService singleThreadExecutor = 
        Executors.newSingleThreadExecutor();
    
    public void handleEventsFixed() {
        singleThreadExecutor.submit(() -> {
            while (true) {
                StateEvent event = eventQueue.take();
                processEvent(event); // 按队列顺序处理
            }
        });
    }
}

// 场景3:状态转换过程中的中断问题
public class StateTransitionBug {
    private Lock stateLock = new ReentrantLock();
    private TaskState state = TaskState.PENDING;
    
    // 问题代码
    public void transitWithBug(TaskState newState) {
        try {
            stateLock.lock();
            validateTransition(state, newState); // 可能抛出异常
            updateState(newState); // 如果上面抛异常,状态可能不一致
        } finally {
            stateLock.unlock();
        }
    }
    
    // 修复方案:使用事务性的状态转换
    @Transactional
    public void transitFixed(TaskState newState) {
        TaskEntity task = taskRepository.findById(taskId)
            .orElseThrow(() -> new TaskNotFoundException(taskId));
        
        validateTransition(task.getState(), newState);
        task.setState(newState);
        taskRepository.save(task);
        publishStateChangeEvent(task);
    }
}

// 场景4:非幂等的状态转换
public class NonIdempotentBug {
    // 问题代码
    public void completeTaskWithBug(String taskId) {
        TaskEntity task = taskRepository.findById(taskId).get();
        task.setState(TaskState.COMPLETED);
        task.setCompletionCount(task.getCompletionCount() + 1); // 多次调用会累加
        taskRepository.save(task);
    }
    
    // 修复方案:实现幂等性
    public void completeTaskFixed(String taskId) {
        taskRepository.updateTaskState(
            taskId, 
            TaskState.RUNNING,  // 预期的当前状态
            TaskState.COMPLETED // 目标状态
        );
    }
}

// 场景5:分布式环境下的状态同步问题
public class DistributedStateBug {
    // 问题代码
    public void processDistributedTaskWithBug(String taskId) {
        TaskEntity task = taskRepository.findById(taskId).get();
        if (task.getState() == TaskState.PENDING) {
            // 其他节点可能已经在处理
            task.setState(TaskState.RUNNING);
            taskRepository.save(task);
        }
    }
    
    // 修复方案:使用分布式锁
    private final DistributedLock distributedLock;
    
    public void processDistributedTaskFixed(String taskId) {
        try {
            if (distributedLock.tryLock(taskId, 5, TimeUnit.SECONDS)) {
                try {
                    TaskEntity task = taskRepository.findById(taskId).get();
                    if (task.getState() == TaskState.PENDING) {
                        task.setState(TaskState.RUNNING);
                        taskRepository.save(task);
                    }
                } finally {
                    distributedLock.unlock(taskId);
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new TaskProcessingException("Failed to acquire lock", e);
        }
    }
}

// 场景6:状态转换的一致性问题
public class StateConsistencyBug {
    // 问题代码
    public void updateRelatedStatesWithBug(String taskId) {
        // 更新主任务状态
        TaskEntity task = taskRepository.findById(taskId).get();
        task.setState(TaskState.COMPLETED);
        taskRepository.save(task);
        
        // 更新子任务状态可能失败
        List<SubTaskEntity> subTasks = subTaskRepository.findByParentId(taskId);
        for (SubTaskEntity subTask : subTasks) {
            subTask.setState(TaskState.COMPLETED);
            subTaskRepository.save(subTask); // 可能抛出异常
        }
    }
    
    // 修复方案:使用事务确保一致性
    @Transactional
    public void updateRelatedStatesFixed(String taskId) {
        TaskEntity task = taskRepository.findById(taskId).get();
        List<SubTaskEntity> subTasks = subTaskRepository.findByParentId(taskId);
        
        // 在一个事务中更新所有相关状态
        task.setState(TaskState.COMPLETED);
        taskRepository.save(task);
        
        for (SubTaskEntity subTask : subTasks) {
            subTask.setState(TaskState.COMPLETED);
            subTaskRepository.save(subTask);
        }
    }
}

标签:task,taskRepository,void,TaskState,偶发性,状态机,public,taskId,bug
From: https://blog.csdn.net/qq_51149892/article/details/144988109

相关文章

  • Transitions:世界上最牛逼的状态机Python库
    引言状态机是一种用于描述和处理事物状态变化的数学模型。它通过定义一系列状态以及在这些状态之间流转转换来模拟复杂的业务逻辑或系统行为。对于开发者而言,实现一个可靠且易于维护的状态机并非易事。然而,随着Python社区的发展,出现了一些优秀的工具可以帮助我们更轻松地构......
  • BUG:SWM32开机绘制lvgl框架下的某个自定义控件死机
    一.BUG描述现象1.画了一个关于"模式"的自定义控件,结果开机绘制总是死机。现象2.用keil进行仿真调试全速运行同样死机,但是如果在异常处加断点,然后单步调试就正常。(注:仿真调试比直接运行的速度要慢)现象3.把这个异常对象的创建代码删除,再后面加四个打印追踪,还是死机;但是删除两个......
  • 开发微信小程序游戏,有没有类似Debug真机图形的方法
    1)开发微信小程序游戏,有没有类似Debug真机图形的方法2)Unity中如何实现动态实时的车削效果3)动态创建的Texture,有什么办法可以让他保持ASTC么4)Unity转微信小游戏的日志问题这是第416篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更......
  • Qt 状态机使用说明
    一、前言1、状态机,有限状态机,FiniteStateMachine,简写FSM。2、状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。3、简单说,状态机就是负责执行各种状态的切换。4、Qt状态机通过Qt......
  • 【FOC】FOC开发遇到的Bug
    引言:本文主要介绍从硬件到软件实现上所遇到的所有bug目录1.硬件1.1晶振1.2运放电路1.3ADC读取异常2.软件2.1芯片启动模式2.2电角度对齐2.3电机发抖是什么原因?2.4SVPWM过调制1.硬件1.1晶振        硬件同事,随便拿了个晶振焊上了,导致与原理图不匹配,软......
  • 【前端面试题】前端中的两个外边距bug以及什么是BFC
    外边距合并问题兄弟组件中,如果一个设置margin-bottom,另一个设置margin-top,会导致外边距出现合并的问题,例如box1设置下边距50px,box2设置上边距20px,那么二者之间的外边距进行合并取最大值,所以二者之间相距只有50px。解决办法:给两个兄弟组件加一个父组件,让父组件开启flex布局.......
  • zenoh webserver SUB 的一个bug
    此问题在1.0.0中存在,1.0.1已经解决了,重新替换插件就可以了,老版本sub对于如下格式的不能生效<keey_expre>?_method=SUB参考资料https://github.com/eclipse-zenoh/zenoh-plugin-webserverhttps://github.com/eclipse-zenoh/zenoh-plugin-webserver/issues/211......
  • 「BugKu CTF」1 和 0 的故事
    题意下发一个大小为\(25\times25\)的01矩阵。分析&代码根据\(25\times25\)的大小,联想到平时的微信付款码就这像素,很可能是一个二维码!但是二维码的四个角一般都是“半空心正方形”(可以打开微信付款码,看看形状),我们将这些角补全,得到二维码的01表示为111111100111......
  • BUGAWAY算法小抄-差分数组
    BUGAWAY算法小抄-差分数组什么是差分数组?差分数组的思想是通过对原始数组进行处理,得到一个新的数组(差分数组),利用该数组来高效地进行区间更新操作。具体来说,差分数组记录的是相邻元素之间的差值,而不是原始数组的元素本身。差分数组的原理1.差分数组的构造:假设有一个数组A=......
  • Verilog5_有限状态机
    一、有限状态机(FiniteStateMachine,FSM)基本概念        有限状态机是由寄存器组和组合逻辑构成的硬件时序电路;        其状态只能在同一时钟跳变沿从一个状态转向另一个状态;状态的选择不仅取决于各个输入值,还取决于当前状态,可用于产生在时钟跳变沿时刻开关......