繁体   English   中英

多个Rhino(java)线程操纵同一个文件

[英]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的嵌入方式,有两种可能性:

  1. 如果代码在犀牛壳执行时,使用sync(f,lock)功能把一个函数成同步于第二个参数,或上的功能this其调用的对象,如果第二个参数是不存在的。 (早期版本仅具有单参数方法,因此,除非您的第三方应用程序使用最新版本,否则您可能需要使用该版本或自行滚动;请参见下文。)

  2. 如果应用程序不是使用Rhino shell,而是使用不包含并发工具的自定义嵌入,则需要滚动自己的版本。 sync的源代码是一个很好的起点(请参阅GlobalSynchronizer的源代码;您应该能够以与Global使用它相同的方式直接使用Synchronizer)。

问题可能是您尝试同步的对象没有在上下文之间共享,而是通过嵌入或其他方式多次创建。 如果是这样,则可能需要使用某种技巧,尤其是如果您无法控制嵌入时。 如果您无法控制嵌入,则可以使用某种要在其上同步的VM全局对象,例如Runtime.getRuntime()或类似的东西(我想不出我立即知道的单个对象,但是我怀疑其中一些具有单例API(例如Runtime的工具。)

对于要同步的对象的另一个候选对象是Packages.java.lang.Class.forName("java.lang.Object")之类的东西,除非嵌入的类,否则在所有上下文中都应引用相同的对象( Object类)加载程序的设置非常不寻常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM