var i = 0;
module.exports = {
add: function() {
i = 0;
i += 1;
var shortly_later = new Date()/1000 + Math.random;
while( (new Date()/1000) < shortly_later) { Math.random() } //prevent optimizations
i += 1;
return i;
}
};
\var adder = require('./onePlusOne');
vertx.eventBus().consumer('doOnePlusOne', function(message) {
var onePlusOne = adder.add();
message.reply({result: onePlusOne })
});
ExecutorService executor = Executors.newCachedThreadPool();
ArrayList<Future<Integer>> results = new ArrayList<>();
for(int i = 0; i < 50; i++) {
results.add(executor.submit(() -> {
Async added = theContext.async();
JsonObject addition = new JsonObject();
vertx.eventBus().<JsonObject>send("doOnePlusOne", new JsonObject(), ar -> {
if ( ar.succeeded() ) {
addition.put("onePlusOne", ar.result().body().getInteger( "result" ));
}
added.complete();
});
added.awaitSuccess();
return addition.getInteger( "onePlusOne" );
}));
}
Overall: 26 wrong values for 1 + 1, 24 right ones.
Overall: 16 wrong values for 1 + 1, 34 right ones.
Overall: 18 wrong values for 1 + 1, 32 right ones.
Overall: 25 wrong values for 1 + 1, 25 right ones.
Overall: 0 wrong values for 1 + 1, 50 right ones.
Overall: 0 wrong values for 1 + 1, 50 right ones.
Overall: 0 wrong values for 1 + 1, 50 right ones.
Overall: 0 wrong values for 1 + 1, 50 right ones.
Javascript has no spec for how to behave in a multi threaded world, and it's assumed that it always runs on a single thread, so the synchronization issues you're seeing are not related to vertx or nashorn, but because the lib you're using never considered the case you would run on a multi threaded environment and implemented proper synchronization.
Now, you can use vertx shared data to help you or avoid using threads yourself with the executor code you're using and just use the vertx event loop.
String loadJvmNpm = "load({name: 'jvm-npm.js', script: \""+jvmNpmAsString + "\"});";
String loadVertxGlobals = "load({name: 'vertx-globals', script: \"" + vertxGlobalDefsAsString + "\"});";
String verticleRequire = "require.noCache('" + verticleName + "', null, true);";
String fullContext = loadJvmNpm + loadVertxGlobals + verticleRequire;
String loadFullContext = "loadWithNewGlobal({script: \"" + fullContext + "\", name: \"" + verticleName + "\"});";
engine.eval(loadFullContext);
Any other global is coming from your libraries so if you want to avoid global state you'll need to fix the whole ecosystem I'm afraid.
Anyway you should look as shared data in vertx as it includes structures that allow you safely to work across threads or verticles.
I'd like to see your test on https://github.com/reactiverse/es4x as I'm proposing it as the future direction of js in vertx.
Context objects from Java code. Multiple JavaScript engines can be created from a Java application, and can be safely executed in parallel on multiple threads."Since vertx has no knowledge of what language it is running it knows nothing about graal so there's no state / context propagated across calls so we could properly isolate the calls.