在 nodejs 中,我们用一个从 1 到 4000000 的循环来检索质数;c 语言中,我们设置若干个线程,定义 count 为 4000000,每个线程做如下操作要:如果 count 大于 0,则取出 count 的值,并计算是否为质数,同时将 count 减 1。根据这个思路,javascript 版本的很容易写:
- var count = 0;
for (j = 1; j < 4000000; j++) {if(zhishu(j)){count++;} }
关键难点就是 c 语言的多线程编程。早期 c/c++ 并没有考虑并行计算的需求,所以标准库中并没有提供多线程支持。而不同的操作系统通常实现也是有区别的。为了避免这种麻烦,我们采用 pthread 来处理线程。
下载 pthread 最新版本。由于我对 gyp 不熟,link 依赖 lib 搞了半天没搞定,最后我的方式是,直接把 pthread 的源代码放到了项目目录下,并在 binding.gyp 中把 pthread.c 添加到源代码列表中,在编译项目的时候把 pthread 也编译一次。修改后的 binding.gyp 是这样的:
- {
- "targets": [
- {
- "target_name": "hello",
- "sources": [ "hello.cc","pthreads/pthread.c" ],
- "include_dirs": [
- "<!(node -e \"require('nan')\")",
- "pthreads"
- ],
- "libraries": ["Ws2_32.lib"]
- }
- ]
- }
当然了,我这种方法很麻烦,如果你们只添加 pthread 中 lib 和 include 目录的引用,并且不出现依赖问题,那是最好的,就没有必要用我的方法来做。
那么接下来就进入 C/C++ 多线程的一切了,定义一个线程处理函数:
- pthread_mutex_t lock;
void *thread_p(void *null){ int num, x=0; do{pthread_mutex_lock(&lock); num=count--; pthread_mutex_unlock(&lock); if(num>0){if(zhishu(num))x++; }else{break;} }while(true); std::cout<<' '<pthread_exit(NULL); return null; }
在线程与线程之间,对于 count 这个变量是相互竞争的,我们需要确保同时只能有一个线程操作 count 变量。我们通过 pthread_mutex_t lock; 添加一个互斥锁。当执行 pthread_mutex_lock(&lock); 时,线程检查 lock 锁的情况,如果已锁定,则等待、重复检查,阻塞后续代码运行;如果锁已释放,则锁定,并执行后续代码。相应的, pthread_mutex_unlock(&lock); 就是解除锁状态。
由于编译器在编译的同时,进行编译优化,如果一个语句没有明确做什么事情,对其他语句的执行也没有影响时,会被编译器优化掉。在上面的代码中,我加入了统计质数数量的代码,如果不加的话,像这样的代码:
- for (int j = 0; j < 4000000; j++) {
- zhishu(j);
- }
是会直接被编译器跳过的,实际不会运行。
添加 addon 的写法已经介绍过了,我们实现从 javascript 接收一个参数,表示线程数,然后在 c 中创建指定数量的线程完成质数检索。完整代码:
- #include <nan.h>
- #include <math.h>
- #include <iostream>
- #include "pthreads\pthread.h"
- #define MAX_THREAD 100
- using namespace v8;
int count=4000000; pthread_t tid[MAX_THREAD]; pthread_mutex_t lock;
void *thread_p(void *null){ int num, x=0; do{pthread_mutex_lock(&lock); num=count--; pthread_mutex_unlock(&lock); if(num>0){if(zhishu(num))x++; }else{break;} }while(true); std::cout<<' '<pthread_exit(NULL); return null; }
NAN_METHOD(Zhishu){NanScope(); pthread_mutex_init(&lock,NULL); double arg0=args[0]->NumberValue(); int c=0; for (int j = 0; j < arg0 && j pthread_create(&tid[j],NULL,thread_p,NULL); } for (int j = 0; j < arg0 && j pthread_join(tid[j],NULL); } NanReturnUndefined();}
void Init(Handle exports->Set(NanSymbol("zhishu"), FunctionTemplate::New(Zhishu)->GetFunction()); }
NODE_MODULE(hello, Init);
来源: http://www.phperz.com/article/17/0502/272150.html