如何在全局作用域JSR223 Post Processor组件中实现代码块同步
同步失效原因
你当前使用synchronized (this)作为锁对象无法实现全局多线程互斥,原因是JMeter中每个线程执行JSR223组件时,会生成独立的脚本运行上下文实例,this指向的是当前线程对应的专属脚本实例,不同线程的this不属于同一个对象,相当于多个线程各自加自己的锁,自然无法实现互斥,所以会出现count值重复的问题。
解决方案
将锁对象替换为整个测试计划全局唯一的共享对象即可,推荐两种实现方式:
方式1:直接使用props作为锁对象
props是JMeter全局唯一的属性对象,所有线程共享同一个实例,直接锁它就能实现全局互斥,修改后代码如下:
synchronized (props) { def count = props.get("count").toInteger() count += 1 props.put("count", count.toString()) log.info(" ==== Current count is ${count} ${__threadNum} ${vars.get('__jm__TG__idx')}=== ") // 你的业务代码放在此处 }
方式2:自定义专属全局锁对象
如果担心锁props会影响其他组件对全局属性的读写操作,可以自己定义一个专门的全局锁对象存在props中,代码如下:
// 仅第一次执行时初始化锁对象,后续直接复用 if (!props.containsKey("globalLock")) { props.put("globalLock", new Object()) } synchronized (props.get("globalLock")) { def count = props.get("count").toInteger() count += 1 props.put("count", count.toString()) log.info(" ==== Current count is ${count} ${__threadNum} ${vars.get('__jm__TG__idx')}=== ") // 你的业务代码放在此处 }
注意事项
- 全局锁会强制锁内代码串行执行,会降低压测并发性能,建议尽量缩小锁包裹的代码范围,避免对压测结果的准确性造成影响。
- 测试启动前建议先初始化props中的count值为0,避免之前测试的残留值干扰验证结果。
内容的提问来源于stack exchange,提问作者Janesh Kodikara
相关产品推荐
相关产品推荐

