我发现自己有点夸张。
我有一个大型应用程序,它有谷歌的V8 JavaScript引擎。在UI线程上对V8引擎进行了一些调用。为了对每个人推荐的用户友好,一些长操作在一个单独的线程上运行,而不会挂起UI线程。但是,这些长时间运行的操作也会调用V8 javascript引擎。所以多线程调用V8。
事实是,V8似乎使用线程本地存储。这似乎使我的应用程序随机爆炸。这绝对属于“这可能到现在为止如何运作?”错误。
如果没有重新设计我的应用程序,我提出了一个丑陋,丑陋可怕的超级黑客攻击:我可以让V8认为它在不同的线程上运行吗?
换句话说,我第一次打电话给V8时,我记下了这个主题。然后,对于对V8 的所有其他调用,我以某种方式欺骗线程,以便线程本地存储/其他任何与线程相关的工作。
可以吗?它会起作用吗?我甚至认为这样一个骗人的黑客是愚蠢的吗?
答案 0 :(得分:19)
你不应该欺骗任何东西。相反,你应该告诉V8你正试图从不同的线程中使用它。
在版本3.2之前的V8中,唯一的方法是在使用不同线程的V8之前使用v8::Locker
。它保证独占访问V8并初始化存储在TLS中的内部结构。有关详细信息,请参阅http://code.google.com/p/v8/source/browse/branches/3.1/include/v8.h#3189
从版本3.2开始,V8具有 isolate 的概念。如果您没有显式创建隔离,V8会隐式创建默认隔离以保持API兼容。在这种情况下,您仍然可以像旧版本一样使用v8::Locker
。如果您明确创建隔离区,那么除了使用v8::Locker
获取独占访问权限之外,您还必须使用v8::Isolate::Enter
/ v8::Isolate::Exit
方法或v8::Isolate::Scope
在线程中明确地输入和退出它们。有关详细信息,请参阅http://code.google.com/p/v8/source/browse/trunk/include/v8.h#3510
在大多数情况下可以使用的简单答案是:在使用不同线程的V8之前使用v8::Locker
。
答案 1 :(得分:1)
我遇到了同样的问题,并设法通过这个线程找到解决方案。要详细说明VE的答案,默认情况下不能使用来自多个线程的v8。如果你愿意,你必须使用隔离和锁。
问题是你不能走到一半,除非你完全退出并破坏你的JS上下文,否则你不能只使用锁。由于在大多数非平凡的情况下都不是这种情况,所以你必须一路走下去,并且
创建自己的v8::Isolate
。你可以使这个全局,但(据我所知)它不能是默认的(因为默认值已经处于输入状态)。
在您调用v8的所有函数中(并且不保证是内部函数),您必须输入您的隔离(使用v8::Isolate::Scope
)和
也使用'v8 :: Locker'对象。
我写了一个小助手对象,我在我的公共方法中使用它看起来有点像这样:
class SessionLock {
private:
v8::Isolate::Scope scope;
v8::Locker lock;
public:
SessionLock() : scope(getSessionIsolate()), lock(getSessionIsolate()) {}
};