不要在同步方法中与生成的线程简单的传递锁
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的线程先放弃锁。应该有更好的方法。
好困,写的乱七八糟,有工夫再改吧。
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的线程先放弃锁。应该有更好的方法。
好困,写的乱七八糟,有工夫再改吧。
相关文章推荐
- 一个简单的C#多线程间同步(事件方法)的例子
- (好~)windows下的线程进程同步方法
- java多线程有几种实现方法?线程之间如何同步
- java导出生成word的简单方法
- Java线程:线程的同步-同步方法
- 简单方法实现1.1.3版iPhone同步显示歌词
- PHP生成指定随机字符串的简单实现方法
- Python使用tablib生成excel文件的简单实现方法
- Java线程同步之静态方法
- .NET多线程编程(13)——一个简单的C#多线程间同步的例子
- OKHttp3同步和异步的简单使用方法
- 用Ogre生成天龙八部的lightmap和minimap的简单方法
- Delphi Dll线程使用Synchronize同步导致线程假死的解决方法
- 『IOS』ios项目生成ipa文件的真正简单可用的方法
- 七、初学Java多线程:向线程传递数据的三种方法(没感觉三种方法有什么区别?)
- 一起谈.NET技术,在Silverligh中调用Javascript (四种调用方法+简单与复杂参数的传递)
- asp简单生成静态的方法(模板标签替换)
- Ajax回调函数不执行、js实现跳转页面并传递值、java生成ID方法、jQ给input赋值
- Java生成静态页面的简单方法和代码
- centos shell编程4【分发系统】 服务器标准化 mkpasswd 生成密码的工具 expect讲解 expect传递参数 expect自动同步文件 expect指定host和要同步的文件 expect文件分发系统 expect自动发送密钥脚本 Linux脚本执行方式 第三十八节课