IronPython中的多线程

时间:2013-06-08 12:34:58

标签: .net multithreading thread-safety ironpython

我在IronPython中有一个“脚本类”,我的应用程序中的脚本通过调用其实例上的方法来工作。我需要从多个线程实现调用脚本。这样做的正确方法是什么?

我有多个问题:

  1. ScriptScope线程安全吗?信息是矛盾的。 ScriptScope's documentation says“ScriptScope不是线程安全的。当多个线程可以访问同一个模块或者应该为每个线程复制时,主机应该锁定。”然而,IronRuby使用相同的DLR和@JimmySchementi says “ScriptRuntime,ScriptEngine和ScriptScope都是线程安全的,旨在用于线程之间。具体来说,ScriptScope使用线程安全的数据存储,因此ScriptScope可以在线程之间共享。” / EM>

  2. 如果我创建了多个ScriptScope,那就意味着多次执行相同的初始化脚本。假设我运行了10个Python脚本文件,导入了5个程序集,并且总体上执行了相当多的代码以使“脚本对象”准备就绪。有没有办法避免为每个线程运行大量相同代码的时间和内存成本?

  3. 正在使ScriptScope变量为线程静态(即应用ThreadStaticAttribute)并为Task.Run使用的每个线程执行初始化?或者我应该使用TaskScheduler并发限制,因为多个范围的成本很高?

  4. 总体而言:如何正确实现在多个线程中的不同参数上运行相同的脚本?脚本必须同时执行,并且不得因竞争条件而崩溃。

3 个答案:

答案 0 :(得分:2)

1

如果ScriptScope的文档说它不是线程安全的,请相信它,或者至少表现得像你相信它。 @JimmySchementi可能已经查看了当前的实现,并确定它当前是线程安全的,但是这并不保证它在下一个类的补丁中会如何表现,更不用说下一个主要版本了。

2

是的,您需要初始化每个ScriptScope。我会尽量减少你需要的ScriptScope数量,如何做到这一点取决于你的设置。如果相关线程的主要目的是托管ScriptScope,那么你应该使用ThreadPool,每个线程都有一个ThreadLocal< ScriptScope>。如果这些线程正在执行其他操作以及运行脚本,那么您应该有一个存储ScriptScopes的对象池,每个线程都可以检出ScriptScopes,完成工作,然后释放ScriptScope。

3

如果沿着这条路走下去,请先将ThreadLocal放在ThreadStatic上。

答案 1 :(得分:0)

如果我理解你的话,这就是你在脚本中的表现方式。

https://github.com/dretax/Python-Plugins/blob/master/PlutonPlugins/PluIRC/PluIRC.py#L154

查看该脚本的功能,它完全启动了具有不同参数的同一事物的新线程。

如果FULLY线程化,你可以看到py文件,并使用IronPython。 那就是你如何正确地做线程,而不是以任何其他方式。

答案 2 :(得分:-1)

因为,看起来你得到一个具体的答案,我有一个普遍的答案。

我的一位同事在我之前的工作中使用过IronPhython并且处理多线程是必不可少的,所以我可以说在生产系统上的多线程环境中运行IronPython是可能的。

我不知道他是否使用了自己的锁定或依赖于IronPython中的锁定。

我建议:

a)自己运行测试。您应该能够编写一个简单的测试来证明它是否安全。像以下代码一样粗糙的东西可能是一个好的开始:

    [Test]
    public void TwoThreadsWithTheirOwnContexts() {
        //Create two threads
        var tasks = new Task[2];
        tasks[0] = Task.Factory.StartNew(PrintSomethingInIronPython1);
        tasks[1] = Task.Factory.StartNew(PrintSomethingInIronPython2);
        Task.WaitAll(tasks);
    }

b)无论如何都要加锁。在您的代码中完成锁定可能不是一个大问题,您将消除不确定性。

最终,如果文档说某些东西不是线程安全的,那么你必须证明它是(测试)或安全(你自己的锁定)。无论如何,在你投入生产之前应该进行多线程测试。我不认为你在开始的时候做任何时候都不会放松。

回复2: 只是一个建议。创建一个初始化一次的池线程,然后重用这些线程。