编程规范---问题单同步

定位一个问题,花了1天左右时间,发现是之前另一个分支上已发现,而且已经提供了解决方案的问题

疑问:这样的问题,不应该花这些时间,如何改进?---------应该在主干和分支之间有定时的同步机制

1. 应该有主干和分支之间的同步流程

2. 这个时间不宜太长,因为太长问题单的修改可能都忘记了,容易出错-------定时同步的话

3. 或:随时有多个主干的环境,同样问题确认在其它环境上是否存在,存在则直接同步问题单-------------当前用禅道是否支持这些功能

 

完整的过程

1. 在K环境上发现,登录每次都失败(偶有成功),怀疑和最近的加密方式增加有关(合理怀疑,因为最近的主要合入是这个)

----------------最终确认不是这个原因

2. 通过增加日志,确认是由于竞争条件(某个线程同一时间只允许一个在运行,实际运行了多个,且第2个运行时,由于第1个未完全退出,导致仅设置了标识位,但未运行,然后后续的线程运行就不能正常启动了)

---------------当前缺少部分日志规范,日志打印的较少,较熟悉才可参根据日志判断

2.1. 线程1运行,将运行标识位置为运行中

2.2. 线程1运行结束前设置标识位为不再运行,并emit 信号,然后,return退出

2.3. 上述emit信号解发了线程2运行,线程2运行时检测到线程1的标识位是不再运行,因此,可以运行(满足同一时间只有1个进程运行的条件),因此开始运行,但此时,线程1的return尚未执行,导致其实际未运行,但标识位置为运行了

2.4. 后续其它线程运行时,检查标识位,由于标识位已由线程2置为运行中,因此,不会执行(同一时间只有一个实例),但线程2由于上述原因实际未执行,导致标识位一直无法置为不再运行,阻塞了后续所有线程

 

3. 按上述原因,重新设计一版线程的标识位,实际有一点问题

----emit是Qt的机制,这里emit肯定会导致后续的问题,所以

3.1. 延迟emit发送-----------可以解决问题,不严谨,这里后面的return执行的时机,不能保证在emit之前,因此,虽然可以解决问题,但不是从根本上

3.2. 重新设计标识位,采用autointer,确保多线程读到的是同一个------------未能解决问题,原因:emit发送会触发进程切换,仍然会走到老路上,会在设置运行标识位false之后,return之前emit,仍会导致问题

3.3. 重新设置标识位,增加锁,并增加进程的完整的状态检查--------------------------未尝试(这个应该是更好的一个方法),在同其它同事的交流过程中,得知其它分支已解决了类似的问题

3.4. 同步原分支的修改即可

4. 当前的改法及其局限

当前改法为:

4.1. 在可能的地方增加延时,并在延迟中判断进程是否仍在运行,如果运行,则继续等待

问题:

4.1. 等待的时间不定,可能需要实际测试

4.2. 这里的函数表义和实际不符,名字为:setSleepTime 实际上应该叫做 runAfterPreThreadFinished或类似,没有体现出这个意思。

4.3. 这里采用简单的方法,虽然能解决问题,但对外面的使用增加了复杂度-----需要setSleepTime()

-----------------------代码见后面

5. 更好的修改方法

5.1. 让Thread体面的结束

-----------------对于这里要emit的,可以放到thread的finished信号中,确保该线程结束后再emit,触发下一次执行,这样后面不需要setSleepTime

5.2. 增加锁以及完整的进程状态判定,不能仅通过标识位来判断

----------------参考上面

5.2.1. 锁、autointer方式保证这个更新,所有地方的缓存一致更新

5.2.2. 在finished里面做完所有事情,再将标识位清空-----如果用标识位的话(建议用enum的状态,而不是标识位)

 

void MessageThread::setSleepTime(ulong nSleepTime)
{
    checkThreadFinished();
    m_nSleepTime = nSleepTime;
}
void MessageThread::checkThreadFinished()
{
    if (isRunning())
    {
        wait();
    }
}
void MessageThread::run()
while (nSleepTime > 0)
                {
                    if (!m_bIsRun)
                    {
                        return;
                    }

                    QThread::msleep(500);
                    nSleepTime -= 500;
                }
 
 
bool MessageThread::isStart()------------------------更完整的进程状态标识来替代这个,而且名称也待商榷,不是start 应该是“还没结束”
{
    return m_bIsRun;
}
posted @ 2025-09-24 09:28  知易  阅读(10)  评论(0)    收藏  举报