CSDN博客

img dhunter

不要在同步方法中与生成的线程简单的传递锁

发表于2004/10/10 3:11:00  515人阅读

多线程程序的调试真是太麻烦了,没有办法debug,全靠看日志分析,昨天晚上遇到的问题今天才解决。
july -- 我现在做的一个工作流项目,目标是构建一个轻量级的流程服务组件。
昨天晚上在做july中的And类型的分支流程的测试时,在join结点活动上,随机的出现不一致的状态变迁。我们的实现逻辑是“活动结束->将令牌传递给变迁->变迁通知下一个活动->一个活动在满足启动条件的情况下从前置变迁中取令牌并运行”,而在似乎在某种情况下一个and join活动的两个前置的transition都通知并且导致了活动的状态转移。活动接到两次通知是正确的,但在第一次通知就能改变活动的状态应该是没有考虑到的,也正是这暴露了对活动状态修改的同步问题。对活动状态的管理我们使用的”july.dblab.jlu.statemachine”是一个我们自己做的自动机组件,问题就出现在它里面。当一个线程在调用statemachine.transform的时候,应该锁定状态机的当前状态,而不应该给其它线程取得当前状态的机会:

void check(){
    synchronized(currentState){
        if(tranform's auto condition meet){
            transformasyn(to);
        }
    }
}

void transform(State to) {
    .....
    synchronized(currentState) {
                beforeStateChange();
                currentState = to;
    }
    afterStateChange();
    .....
}

void transformasyn(State to){
    new thread to call transform;
}

问题出在检查当前状态的函数check()中, 它调用的是异步的transform方法,所以有可能在新生成的transform线程还没有来的及锁定住当前状态时,调用check()的线程已经放开了对currentState的锁定,自然其它线程就有机会乘虚而入。而事实上对statemachine的设计要求也仅仅是确定自动机而已,所以在check中可能执行的变迁只有一条,调用异步的transform是没有意义的,所以直接同步调用,应该就没问题了。

结论: 不要试图在同步方法中与新生成的线程简单的传递锁,这样会留下同步的空隙,而且机率相当的高:因为线程的构造相对是耗时的,在相当的情况下都是check的线程先放弃锁。应该有更好的方法。

好困,写的乱七八糟,有工夫再改吧。
0 0

相关博文

我的热门文章

img
取 消
img