推荐我在github上的一个重构项目mvelx

2016/11/19 16:01:33 No Comments

近半年时间一直在对mvel项目中的代码尝试进行翻译,在翻译的过程当中,就有一个对人家的代码进行修改的冲动。但考虑到很多使用此框架的人,在碰到问题时都是对照的原来的代码。因此在翻译过程中,对原来的代码和注解不作任何调整,所有的操作都是作添加处理。待大部分的功能都进入尾声,相应的重构项目的日程也提上来。

恰好在项目中碰到一个需要对mvel功能作调整才能支持的例子,因此就此在github上新开一个项目,重构原来的mvel,并且在加上相应的功能代码之后,决定作为一个新的项目进行发布,并且所有的代码都保证开源方式。

想了解mvel是什么,可以先google一下,作为一个表达式引擎,它能够支持大部分的表达式工作场景。但对于想要了解这一种引擎的开发人员来说,没有一个有效的注释和相应的开发思路,是很难了解到底是什么东西。并且如果只是想使用,不深入其中,是不会明白一个表达式引擎是如何工作的。

相应的git项目地址:https://github.com/flym/mvelx
目的:用于提供mvel的中文注释版,并且删除在实际开发中不再使用的代码,提供一个简单的脚本执行引擎

希望得到支持

使用guava Striped中的lock导致线程死锁的问题分析

2016/11/19 15:04:00 No Comments

在最近的开发调试当中,一个多线程的项目出现了线程死锁的问题。按照正常的解决思路,上监控工具yourkit或者自己打印出线程信息,最终的显示信息均为lock对象先拿到了自己的锁,然后去拿对方的锁,现状是这样的。但与一些正常的项目相比,按照正常的执行情况,是不可能出现死锁的。

项目使用了程序锁来保证并发情况下,一些操作只能由单个来执行,如一些不允许多次运行的场景。所谓程序锁,即通过由锁池获取相应的lock对象,然后进行lock操作,在相应的方法体内进行相应的控制。
项目中使用基于guava的striped来获取不同的锁,本来原来的代码是自己封装实现,但考虑到guava已经提供,因此直接使用了,相应的伪代码如下所示:

        Striped<Lock> lockStriped = Striped.lazyWeakLock(1024);

        Lock lock = lockStriped.get("动态生成的临界资源标识符");
        lock.lock();
        try{
            //执行业务操作
        } finally {
            lock.unlock();
        }

以上的代码因为足够的通用,因此被封装为一个LockAdvice,以实现通用的锁方法操作,只需要在需要加锁的方法上加上Lockable注解,就可以达到所要的效果。出现死锁的2个线程表现如下:

//线程1
加锁获取资源类型1
加锁获取资源类型2

//线程2
加锁获取资源类型1
加锁获取类型类型2

从上面的线程操作来看,加锁的顺序是一样的,释放锁的顺序也一致,因此理论上不会出现死锁。为保证锁切面的简单实现,上面的锁资源类型1 被表现为一个字符串,即通过不同的字符串来进行描述。也就是说,在上面的现象中,会有4个字符串进行锁的key进行操作。

问题场景被发现了,并且这个问题肯定会产生,多线程运行一段时间之后就会发生。查找问题产生的原因却很漫长。不知道为什么,使用jstack却没有打印出每个线程在哪一个环节持有哪个锁(是不是本身就没有),通过jstack的信息表示,相应的线程肯定持有对方的锁,而对方也在等级已方的锁,并且相应的锁的发生点也确定是在相应的锁切面准备执行的时候。剩下的问题就是看是否是相应的锁生成器striped本身就返回了相同的锁,如果由锁生成器本身就返回相同的锁,那么就肯定有问题了。

(more…)