您的位置:首页 > 其它

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

2004-10-10 03:11 239 查看
多线程程序的调试真是太麻烦了,没有办法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的线程先放弃锁。应该有更好的方法。

好困,写的乱七八糟,有工夫再改吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: