Libuv Thread句柄
libuv使用线程池对多个线程进行管理,而且它也提供了用户创建线程的功能。
POSIX
可移植操作系统接口(英语:Portable Operating System Interface,缩写为POSIX),POSIX是IEEE为要在各种UNIX操作系统上运行软件,而定义API的一系列互相关联的标准的总称,其正式称呼为IEEE Std 1003,而国际标准名称为ISO/IEC 9945。此标准源于一个大约开始于1985年的项目。POSIX这个名称是由理查德·斯托曼(RMS)应IEEE的要求而提议的一个易于记忆的名称。它基本上是Portable Operating System Interface(可移植操作系统接口)的缩写,而X则表明其对Unix API的传承。
在Linux系统下的多线程遵循POSIX标准,而其中的一套常用的线程库是 pthread ,它是一套通用的线程库,是由 POSIX 提出的,因此具有很好的可移植性,我们学习多线程编程,就是使用它,必须包含以下头文件:
#include <pthread.h>
除此之外在链接时需要使用库libpthread.so。因为pthread的库不是Linux系统的库,所以在编译时要加上 -lpthread 选项。
API函数
libuv线程句柄是Linux线程的typedef,如下:
//libuv/include/uv/unix.h
typedef pthread_t uv_thread_t;
创建线程
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { uv_thread_options_t params; params.flags = UV_THREAD_NO_FLAGS; return uv_thread_create_ex(tid, ¶ms, entry, arg); } /* 这才是真正创建线程的地方 */ int uv_thread_create_ex(uv_thread_t* tid, const uv_thread_options_t* params, void (*entry)(void *arg), void *arg) { int err; pthread_attr_t* attr; pthread_attr_t attr_storage; size_t pagesize; size_t stack_size; /* Used to squelch a -Wcast-function-type warning. */ union { void (*in)(void*); void* (*out)(void*); } f; stack_size = params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0; attr = NULL; if (stack_size == 0) { stack_size = thread_stack_size(); } else { pagesize = (size_t)getpagesize(); /* Round up to the nearest page boundary. */ stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1); #ifdef PTHREAD_STACK_MIN if (stack_size < PTHREAD_STACK_MIN) stack_size = PTHREAD_STACK_MIN; #endif } if (stack_size > 0) { attr = &attr_storage; if (pthread_attr_init(attr)) abort(); if (pthread_attr_setstacksize(attr, stack_size)) abort(); } /* 最终调用线程库 pthread 的pthread_create()函数创建线程*/ f.in = entry; err = pthread_create(tid, attr, f.out, arg); if (attr != NULL) pthread_attr_destroy(attr); return UV__ERR(err); }
线程分离状态
int uv_thread_join(uv_thread_t *tid) { return UV__ERR(pthread_join(*tid, NULL)); }
获取线程句柄
uv_thread_t uv_thread_self(void) {
return pthread_self();
}
判断线程是否相同
int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
return pthread_equal(*t1, *t2);
}
其实还有很多互斥锁、信号量相关的实现都是差不多的,说白了就是在操作系统之上抽象了一个操作系统模拟层 。
Demo
#include <stdio.h>
#include <unistd.h>
#include <uv.h>
void hare_entry(void *arg)
{
int track_len = *((int *) arg);
while (track_len) {
track_len--;
sleep(1);
printf("hare ran another step\n");
}
printf("hare done running!\n");
}
void tortoise_entry(void *arg)
{
int track_len = *((int *) arg);
while (track_len)
{
track_len--;
printf("tortoise ran another step\n");
sleep(3);
}
printf("tortoise done running!\n");
}
int main() {
int track_len = 10;
uv_thread_t hare;
uv_thread_t tortoise;
uv_thread_create(&hare, hare_entry, &track_len);
uv_thread_create(&tortoise, tortoise_entry, &track_len);
uv_thread_join(&hare);
uv_thread_join(&tortoise);
return 0;
}
运行结果
tortoise ran another step
hare ran another step
hare ran another step
tortoise ran another step
hare ran another step
hare ran another step
hare ran another step
tortoise ran another step
hare ran another step
hare ran another step
hare ran another step
tortoise ran another step
hare ran another step
hare ran another step
hare done running!
tortoise ran another step
tortoise ran another step
tortoise ran another step
tortoise ran another step
tortoise ran another step
tortoise ran another step
tortoise done running!