理解v8的Isolate调度

来源:互联网 发布:数据预测算法有哪些 编辑:程序博客网 时间:2024/06/06 03:08

这两天看了一下v8的在多线程情况下多个Isolate的调度原理,别的不多说了还是先看一下测试代码吧

#include <v8.h>#include <iostream>#include <pthread.h>#include <unistd.h>using namespace v8;typedef struct _Args{Isolate* isolate;char message[256];} Args;void* test(void* data){Args* args = (Args*) data;Isolate* isolate = args->isolate;if (isolate == NULL){std::cout << "null isolate found" << std::endl;delete args;return NULL;}Isolate* current = Isolate::GetCurrent();if (current == NULL){std::cout << "current isolate is null before locker" << std::endl;}else{std::cerr << "current isolate is not null before locker" << std::endl;}Locker locker(isolate);current = Isolate::GetCurrent();if (current != NULL){std::cerr << "current isolate is not null after locker" << std::endl;}else{std::cout << "current isolate is null after locker" << std::endl;}Isolate::Scope isolate_scope(isolate);current = Isolate::GetCurrent();if (current == NULL){std::cerr << "current isolate is null after enter" << std::endl;}else{std::cout << "current isolate is not null after enter" << std::endl;}// Create a stack-allocated handle scope.HandleScope handle_scope(isolate);// Create a new context.Handle<Context> context = Context::New(isolate);// Here's how you could create a Persistent handle to the context, if needed.Persistent<Context> persistent_context(isolate, context);// Enter the created context for compiling and// running the hello world script.Context::Scope context_scope(context);// Create a string containing the JavaScript source code.Handle<String> source = String::New(args->message);// Compile the source code.Handle<Script> script = Script::Compile(source);// Run the script to get the result.Handle<Value> result = script->Run();// The persistent handle needs to be eventually disposed.persistent_context.Dispose();// Convert the result to an ASCII string and print it.String::AsciiValue ascii(result);for (int i = 0; i < 3; i++){std::cout << *ascii << std::endl;sleep(1);}delete args;return NULL;}int main(int argc, char* argv[]){pthread_t pids[256];int num = 3;for (int i = 0; i < num; i++){Args* args = new Args();args->isolate = Isolate::New();int n = sprintf(args->message, "\"first thread\" + %d", i);args->message[n] = '\0';int ret = pthread_create(&pids[i], NULL, test, args);if (ret != 0){std::cout << "create pthread" << i << " failed" << std::endl;return 1;}}for (int i = 0; i < num; i++){pthread_join(pids[i], NULL);}std::cerr << "first test loop done" << std::endl;Isolate* isolate = Isolate::New();{Locker locker(isolate);Isolate::Scope scope(isolate);}for (int i = 0; i < num; i++){pids[i] = 0;Args* args = new Args();args->isolate = isolate;int n = sprintf(args->message, "\"second thread\" + %d", i);args->message[n] = '\0';int ret = pthread_create(&pids[i], NULL, test, args);if (ret != 0){std::cout << "create pthread" << i << " failed" << std::endl;return 1;}}for (int i = 0; i < num; i++){pthread_join(pids[i], NULL);}std::cerr << "second test loop done" << std::endl;Isolate* current = Isolate::GetCurrent();for (int i = 0; i < num; i++){pids[i] = 0;Args* args = new Args();args->isolate = current;int n = sprintf(args->message, "\"third thread\" + %d", i);args->message[n] = '\0';int ret = pthread_create(&pids[i], NULL, test, args);if (ret != 0){std::cout << "create pthread" << i << " failed" << std::endl;return 1;}}for (int i = 0; i < num; i++){pthread_join(pids[i], NULL);}std::cerr << "third test loop done" << std::endl;return 0;}

运行结果如下:

current isolate is null before lockercurrent isolate is null before lockercurrent isolate is null after lockercurrent isolate is not null after entercurrent isolate is null before lockerfirst thread2current isolate is null after lockercurrent isolate is not null after entercurrent isolate is null after lockercurrent isolate is not null after enterfirst thread1first thread0first thread2first thread1first thread0first thread2first thread1first thread0first test loop donecurrent isolate is null before lockercurrent isolate is null before lockercurrent isolate is null after lockercurrent isolate is not null after entercurrent isolate is null before lockersecond thread0second thread0second thread0current isolate is null after lockercurrent isolate is not null after entersecond thread1second thread1second thread1current isolate is null after lockercurrent isolate is not null after entersecond thread2second thread2second thread2second test loop donecurrent isolate is null before lockercurrent isolate is null before lockercurrent isolate is null before lockercurrent isolate is not null after lockercurrent isolate is not null after enterthird thread0third thread0third thread0current isolate is not null after entercurrent isolate is not null after lockerthird thread1third thread1third thread1current isolate is not null after entercurrent isolate is not null after lockerthird thread2third thread2third thread2third test loop done
第一组测试是完成多个Isolate对象分别在不同的thread里运行的情况,从结果可以看到,这些Isolate在并行执行,并且当执行了Isolate::Scope之后Isolate::GetCurrent返回值也不空了
第二组测试是完成一个Isolate对象分别在不同的thread里运行的情况,从结果可以看到,这个Isolate实际上是顺序在执行的,同样的,执行了Isolate::Scope之后,Isolate::GetCurrent返回值也不空了
第三组测试是完成DefaultIsolate对象分别在不同的thread里运行的情况,从结果可以看到,DefaultIsoalte实际上也是顺序在执行的,但是与第二组不同的是,Locker执行完成之后Isolate::GetCurrent就已经不空了
其实到了这里,已经很明显了,Locker是用来保证一个Isolate必定同时在一个thread里运行,Isolate::Scope实际上只执行了一句代码Isolate::Enter,它负责将thread local store数据写入,保证后面的执行中依赖于tls的地方都不会出问题,而为什么第三组用DefaultIsolate出现了不同的结果呢
原因其实就在于Locker里对DefaultIsolate做了处理,直接Enter了,看代码
 if (isolate_->IsDefaultIsolate()) {      // This only enters if not yet entered.      internal::Isolate::EnterDefaultIsolate();    }


原创粉丝点击