[groovy-user] groovy binding is threadsafe?

400 views
Skip to first unread message

bhm

unread,
Aug 9, 2012, 1:49:38 PM8/9/12
to us...@groovy.codehaus.org
I have code like following

https://gist.github.com/3306301


I'm caching Class object returned from GroovyClassLoader and calling
InvokerHelper.createScript(scriptclass, binding).run()

InvokerHelper.createScript(scriptclass, binding) can be called from
multiple threads for different binding instances but same scriptclass,
from my tests it seems its threadsafe.

I just want to confirm with experts if I'm not missing anything.

Thanks for help.

// code
//
public class Script {
private static final GroovyClassLoader GCL = new
GroovyClassLoader(); // XXX GroovyClassLoader is threadsafe ?

private final Class scriptClass;

public Script(String script) throws CompilationFailedException {
scriptClass = GCL.parseClass(script);
}

public Object invoke(Binding binding) {
groovy.lang.Script gscript =
InvokerHelper.createScript(scriptClass, binding); // XXX
InvokerHelper.createScript is threadsafe?
return gscript.run();
}

public static void main(String[] args) throws Exception {
String my_groovy_script_as_string = "(foo, bar) = [bar, foo];";

final Script script = new Script(my_groovy_script_as_string);

Runnable task = new Runnable() {
public void run() {
Binding binding = new Binding();
binding.setVariable("foo", UUID.randomUUID().toString());
binding.setVariable("bar", UUID.randomUUID().toString());
script.invoke(binding);
}
};

Thread[] pool = new Thread[] {new Thread(task), new
Thread(task), new Thread(task)};

for (Thread t : pool) t.start();
for (Thread t : pool) t.join();
}
}

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


Guillaume Laforge

unread,
Aug 9, 2012, 2:53:10 PM8/9/12
to us...@groovy.codehaus.org
Binding might be as thread-safe as the variable Map you're passing it.
--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one

bhm

unread,
Aug 9, 2012, 3:37:35 PM8/9/12
to us...@groovy.codehaus.org
Thanks,

is it possible to cache Script instance (similar to that is created by
InvokerHelper.createScript) and pass binding as argument to a method
rather then setting on object state. Would there be any benefit of
keeping Script instance (possible use from multiple threads) and call
it with different arguments (bindings) rather then creating a Script
instance for each call that needs different bindings.

Jochen Theodorou

unread,
Aug 13, 2012, 2:52:52 AM8/13/12
to us...@groovy.codehaus.org
Am 09.08.2012 21:37, schrieb bhm:
> Thanks,
>
> is it possible to cache Script instance (similar to that is created by
> InvokerHelper.createScript) and pass binding as argument to a method
> rather then setting on object state.

by default not, no. But I think it wouldn't be too difficult to do. Main
disadvantage is then, that methods you defined in the script cannot
access the binding any more, unless you transport the binding. But well,
that should be clear.

> Would there be any benefit of
> keeping Script instance (possible use from multiple threads) and call
> it with different arguments (bindings) rather then creating a Script
> instance for each call that needs different bindings.

It is certainly possible to reuse the script instances. You can use
setBinding to set a new Binding. But I would still use one
script/binding per thread. If it is save to share the Binding or not
depends on your implementation

bye blackdrag

--
Jochen "blackdrag" Theodorou - Groovy Project Tech Lead
blog: http://blackdragsview.blogspot.com/
german groovy discussion newsgroup: de.comp.lang.misc
For Groovy programming sources visit http://groovy-lang.org

Paul Bennett

unread,
Aug 13, 2012, 8:42:18 AM8/13/12
to us...@groovy.codehaus.org
Our application caches many compiled scripts and runs them with different bindings at different times. However, we make sure that the executions are single-threaded. The Script class holds it's binding in a private variable, so I think it would be impossible to have multiple threads safely accessing the same instance with different bindings.

The big overhead here is compiling the script class, not running it - which I think is definitely shareable. The script classes are cached in a classloader, so it seems possible to have a single, shared classloader holding the compiled script classes, and create separate instances of them per-thread. You could then execute each instance with a separate binding. You would have to dig down and call some lower level Groovy primitives to do this, but it seems possible to me. You might have to make the classloader access and script creation thread-safe, but the execution could definitely be per-thread. With a Thread variable, you could even cache instances per-thread. You'd need some kind of naming scheme to do this, but mechanism to do this is there already

Off the top of my head, I can't remember which methods would be appropriate, but if you look on Script, GroovyClassLoader and InvokerHelper, you should be able to find the right incantation. And of course, the script content *itself* would need to be multi-thread aware....

-pb
Reply all
Reply to author
Forward
0 new messages