[英]Multiple Rhino (java) threads manipulate the same file
我正在使用嵌入式Rhino的第三方应用程序中编写一段javascript(ecmascript)。 该应用程序可以启动多个Java线程来同时处理数据。 似乎每个Java线程都启动其自己的嵌入式Rhino上下文,从而依次运行我的脚本。
我的脚本的目的是,从应用程序接收数据并使用它来维护特定文件的内容。 我需要一个故障保护解决方案来处理脚本中的并发问题。
到目前为止,我想出的是调出java并使用java.nio.channels.FileLock
。 但是, 此处的文档指出:
文件锁代表整个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的多个实例之间似乎不起作用。
更新
我已经尝试过将org.mozilla.javascript.tools.shell.Global
作为模板使用Synchronizer
的建议:
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()
函数。 我的代码有什么问题?
根据Rhino的嵌入方式,有两种可能性:
如果代码在犀牛壳执行时,使用sync(f,lock)
功能把一个函数成同步于第二个参数,或上的功能this
其调用的对象,如果第二个参数是不存在的。 (早期版本仅具有单参数方法,因此,除非您的第三方应用程序使用最新版本,否则您可能需要使用该版本或自行滚动;请参见下文。)
如果应用程序不是使用Rhino shell,而是使用不包含并发工具的自定义嵌入,则需要滚动自己的版本。 sync
的源代码是一个很好的起点(请参阅Global和Synchronizer的源代码;您应该能够以与Global使用它相同的方式直接使用Synchronizer)。
问题可能是您尝试同步的对象没有在上下文之间共享,而是通过嵌入或其他方式多次创建。 如果是这样,则可能需要使用某种技巧,尤其是如果您无法控制嵌入时。 如果您无法控制嵌入,则可以使用某种要在其上同步的VM全局对象,例如Runtime.getRuntime()
或类似的东西(我想不出我立即知道的单个对象,但是我怀疑其中一些具有单例API(例如Runtime
的工具。)
对于要同步的对象的另一个候选对象是Packages.java.lang.Class.forName("java.lang.Object")
之类的东西,除非嵌入的类,否则在所有上下文中都应引用相同的对象( Object
类)加载程序的设置非常不寻常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.