Reputation: 307
I´m working on a JMeter testplan which is meant to preformance-test a webservice. The main part of the whole testplan consists of two steps.
If I use a singlethreaded plan, everything works out as expected, but as soon as I use more than one thread, I get into a race condition. The problem is, that the 2nd step changes the list of avaiable IDs, thus: if thread B retrieves the ID-list before thread A finished step 2, thread B might get the same ID as thread A which leads to an error when thread B tries to fulfill step 2. Somehow a classical example of race conditions in a multithreaded environment. As JMeter doesn´t provide the possibility for defining critical code blocks, I decided to write my own custom Java sampler extending the JMeter-AbstractJavaSamplerClient, overriding runTest() a.s.o. Within the runTest()-implementation I acquire a ReentrantLock and use it to lock the critical code block. The point is, that JMeter doesn´t seem to care about that lock and I simply don´t get why...if I debug my code via remote debugging using Eclipse I see that several threads step into the locked code at the same time, which shouldn´t be the case. I also tried the old fashioned way using synchronize for the complete runTest()-implementation, but that doesn´t work either.
Does anyone have a suggestion what needs to be changed? Or at least an explanation why this doesn´t work?
Thanks in advance!
Upvotes: 2
Views: 1992
Reputation: 31
Another workaround is by compiling a simple java class compile it and put it into the {JMETER_HOME}\apache-jmeter-3.1\lib\ext\
folder.
import java.util.*;
public class Global {
public static Map map = new Hashtable();
}
Export it into a jar file using CMD
jar cvfe {EXPORT_JAR_NAME}.jar ClassName {CLASS_FILE_NAME}.class
Place the file into {JMETER_HOME}\apache-jmeter-3.1\lib\ext\
folder.
Create a Test Action and add a JSR223 PreProcessor into the test plan Show Image
import java.util.concurrent.Semaphore;
Global.map.clear();
Global.map.put("sem", new Semaphore(1));;
Create another Test Action and add a JSR223 PreProcessor into the test plan Show Image
log.info(ctx.getThreadNum() + " ACQUIRE");
Global.map.get("sem").acquire();
for (def i = 0; i < 100; i++) {
// Do something
log.info(ctx.getThreadNum() + " DO SOMETHING " + i);
}
Global.map.get("sem").release();
log.info(ctx.getThreadNum() + " RELEASE");
It should overcome the race condition as Semaphore is synchronized among thread groups.
Upvotes: 2
Reputation: 307
I finally got it running...I didn´t declare my Lock to be static...thus it was possible that several threads entered the critical code block.
Upvotes: 0
Reputation: 168247
There are 2 options on how you can work it around without having to write your own sampler.
Any of Beanshell test elements (Sampler, Post Processor, Pre Processor, Assertion, etc.) provides access to something called vars
which is shorthand for JMeterVariables class instance. So you should be able to use:
vars.put("key", "value"); // to add a variable
vars.remove("key"); // to remove variable
methods anywhere in your test.
See How to use BeanShell: JMeter's favorite built-in component guide for more details and kind of Beanshell cookbook.
Upvotes: 0