【发布时间】:2015-06-24 13:17:49
【问题描述】:
我正在使用嵌入式 Rhino 的第 3 方应用程序中编写一段 javascript (ecmascript)。应用程序可能会启动多个 Java 线程来同时处理数据。似乎每个 Java 线程都启动了自己的嵌入式 Rhino 上下文,然后运行我的脚本。
我的脚本的目的是从应用程序接收数据并使用它来维护特定文件的内容。我需要一个故障安全解决方案来处理脚本中的并发。
到目前为止,我想出的是调用java并使用java.nio.channels.FileLock。但是,文档here 指出:
代表整个 Java 虚拟机持有文件锁。它们不适用于控制同一虚拟机内的多个线程对文件的访问。
果然,阻塞调用FileChannel.lock()没有阻塞反而抛出异常,导致如下丑陋的代码:
var count = 0;
while ( count < 100 )
{
try
{
var rFile = new java.io.RandomAccessFile(this.mapFile, "rw");
var lock = rFile.getChannel().lock();
try
{
// Here I do whatever the script needs to do with the file
}
finally
{
lock.release();
}
rFile.close();
break;
} catch (ex) {
// This is reached whenever another instance has a lock
count++;
java.lang.Thread.sleep( 10 );
}
}
问:如何安全可靠地解决这个问题?
我看到过有关 Rhino sync() 与 Java synchronized 相似的帖子,但这似乎在 Rhino 的多个实例之间不起作用。
更新
我尝试过使用Synchronizer 和org.mozilla.javascript.tools.shell.Global 作为模板的建议:
function synchronize( fn, obj )
{
return new Packages.org.mozilla.javascript.Synchronizer(fn).call(obj);
}
接下来,我使用这个函数如下:
var mapFile = new java.io.File(mapFilePath);
// MapWriter is a js object
var writer = new MapWriter( mapFile, tempMap );
var on = Packages.java.lang.Class.forName("java.lang.Object");
// Call the writer's update function synchronized
synchronize( function() { writer.update() } , on );
但是我看到两个线程同时进入update() 函数。我的代码有什么问题?
【问题讨论】:
-
sync() 在单个 Rhino 实例中的所有上下文之间以及在单个 VM 中运行的所有 Rhino 实例之间工作,我假设这就是我们正在谈论的(它使用 Java 同步,所以也可以与原生 Java 并发工具配合使用)。
-
我的猜测是,在无法测试您的设置(也无法亲自测试我的理论)的情况下,无法使用
Class java.lang.Object作为this调用函数。尝试return new Packages.org.mozilla.javascript.Synchronizer(fn,obj),然后调用返回的函数:synchronize(function() { writer.update() }, on)();,看看是否更好。 -
我得到一个错误
org.mozilla.javascript.EvaluatorException: Java constructor for "org.mozilla.javascript.Synchronizer" with arguments "function,java.lang.Class" not found.查看源代码,确实没有构造函数,我必须传入(Scriptable,Object)。 -
是的,但一切都是对象。 Rhino 翻译这个论点的方式肯定有一些问题。或者你使用的是早期版本的 Rhino,也许?
Packages.org.mozilla.javascript.Context.getCurrentContext().getImplementationVersion()带给你什么? -
也许你是对的:
Rhino Version: Rhino 1.6 release 7 2007 08 19这似乎有点老了。不幸的是,我无法控制(此版本的)应用程序。不过,我会告诉开发团队在下一个版本中开始使用 [rd]ecent 版本。
标签: javascript java multithreading synchronization rhino