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

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

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

多线程执行父类和子类中的同步方法的结论

结论: 父类和子类中分别有一个同步方法(没有重写),然后开启两个线程分别执行其中一个同步方法,最终结果是串行。结论:父类和子类中的同步方法是同一个锁。测试代码如下: SynParent...
  • Mr_Tony
  • Mr_Tony
  • 2017年05月05日 16:57
  • 422

synchronized静态同步方法与非静态同步方法,同步语句块

进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁。        对代码进行同步控制我们可以选择同步方法,也可以选择同步块,这两种方式各有优缺点,至于具体选择什么方式,就见仁见智了,同步...
  • WannerWang
  • WannerWang
  • 2016年03月23日 16:04
  • 1387

java有几种方法可以实现一个线程?用什么关键字修饰同步方法?

java多线程实现方法主要有3种:继承Thread类、实现Runnable接口和使用ExecutorService、callable、future实现有返回结果的多线程。其中前2方式线程执行完后都没有...
  • fogmeng2011
  • fogmeng2011
  • 2015年03月12日 22:37
  • 1348

当同步方法被锁住时,非同步方法是否可以访问同步方法中改变的变量?

考虑如下情景:   一个class 中有一个成员变量b。     成员方法m1()为同步方法, 并且对b进行操作。    成员方法m2()不是同步方法,并且访问b。    那么如果在m1() ...
  • LTianchao
  • LTianchao
  • 2014年04月07日 17:06
  • 1424

Windows核心编程笔记(7)----内核模式下的线程同步

1、内核对象同步与用户模式下同步对比 使用内核对象的唯一缺点就是性能,调用内核对象函数时,调用线程必须从用户模式切换到内核模式,这种切换是相当 耗时的。 内核对象(进程、线程、作业)要么处于触发...
  • mfcing
  • mfcing
  • 2015年03月01日 10:07
  • 1347

C#之线程同步方法

目的在于需要控制一个服务器对于客户端的多线程使用的共享资源的控制 毕设聊天室中使用了一个链表将多个客户端的信息保存了起来 在用户需要交互操作的时候需要使用这个链表 主要锁起来的地方在于链表元素的插入和...
  • u013427969
  • u013427969
  • 2016年05月23日 09:22
  • 406

线程同步常用方式与区别

在介绍线程同步/互斥之前,我们先要理解同步与互斥的概念,引用书上的解释来说明这2个概念: 1、线程(进程)同步的主要任务 在引入多线程后,由于线程执行的异步性,会给系统造成混乱,特别是在急用临界资...
  • drdairen
  • drdairen
  • 2017年06月20日 14:02
  • 561

同步代码块、同步方法、锁总结

同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块,其语法如下: synchronized(obj){ //同步...
  • weixin_36937689
  • weixin_36937689
  • 2017年06月07日 22:34
  • 232

子类覆盖掉父类的同步方法

1、如果父类中的某个方法使用了synchronized关键字,而子类中也覆盖了这个方法,默认情况下子类中的这个方法并不是同步的,必须显示的在子类的这个方法中加上synchronized关键字才可。 ...
  • shinecjj
  • shinecjj
  • 2016年08月01日 19:07
  • 1879

Java多线程锁释放

Java多线程锁释放
  • paincupid
  • paincupid
  • 2016年06月20日 23:19
  • 2215
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:不要在同步方法中与生成的线程简单的传递锁
举报原因:
原因补充:

(最多只允许输入30个字)