V8 is not thread-safe. Just look at the code for HandleScopes, located in handles.h:
static v8::ImplementationUtilities::HandleScopeData current_; const v8::ImplementationUtilities::HandleScopeData previous_;
The way HandleScopes work is simple: each handle is allocated in the current handle scope (HandleScope::current_). When a new HandleScope is created, it sets its previous_ to the previous one, and changes current_ to itself. The current handle scope is stored statically — in short, shared between all threads.
Logic dictates that this would cause problems in multithreading. Big time.
Consider the following overly simplified example:
//thread 1 HandleScope handle_scope; //thread 2 HandleScope handle_scope; //thread 1 Local<Value> test = String::New("test"); //allocated in thread 2's context scope! //thread 2 closes, destroying its handle scope, and thus //test, which was allocated inside of it return; //thread 1 continues, and likely crashes, as it tries to use test, which was //mistakenly allocated inside of thread 2's handle scope (and thread 2's //handle scope has now ended). if (test->IsString()) { }
“That’s why that is no work.”
Update: With enough locking, it is possible. v8 even has a Locker object to help. But it is still quite tricky, and appears to be prone to failure. I haven’t tested it much myself, as I currently don’t have a need for threading.
It would still be quite dangerous, especially if one unlocks while inside of a HandleScope.
Tags: multithreading