线程的创建

2014-09-25 20:58:30   最后更新: 2014-09-26 10:54:36   访问数量:1216




每个进程开始运行时,都只包含一个控制线程

新增线程需要调用 pthread_create 函数创建

int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void), void *restrict arg);

 

定义于 pthread.h 中

调用成功返回0,否则返回错误编号

 

当 pthread_create 成功返回时,由 tidp 指向的内存单元被设置为新创建的线程ID

attr 用来指定各种不同的线程属性,为 NULL 则创建默认属性线程

新创建的线程从 start_rtn 回调函数开始执行,并以 arg 作为回调参数,参数虽然只有一个,但是可以为任何类型的指针类型,所以可以创建参数结构体传参

 

进程在创建线程时无法指定哪个线程先执行

新的线程继承调用线程的浮点环境和信号屏蔽字,但是会清除未决信号集

 

需要注意的是,pthread_create 函数调用失败时并不设置 errno,而是返回错误码

每个线程都有自己的 errno 副本,这只是为了与现有函数兼容

 

下面的程序打印了线程ID

/* * file: main.c * author: 龙泉居士 * date: 2014-09-26 09:02 */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> pthread_t ntid; void printids(const char *s) { pid_t pid; pthread_t tid; pid = getpid(); tid = pthread_self(); printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int)pid, (unsigned int)tid, (unsigned int)tid); } void *thr_fn(void *arg) { printids("new thread: "); return 0; } int main() { int err; err = pthread_create(&ntid, NULL, thr_fn, NULL); if (err != 0) { printf("cannot create thread: %s\n", strerror(err)); return -1; } printids("main thread:"); sleep(1); return 0; }

 

需要注意的是,由于pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a所以在编译中要加 -lpthread参数

# FILE: Makefile # AUTHOR: 龙泉居士 # DATE: 2014-09-26 09:52 CC = gcc CFLAGS = -Wall -g FILE = main ${FILE} : ${FILE}.o ${CC} ${CFLAGS} -o $@ $^ -lpthread .PHONY: clean clean: rm -rf ${FILE} ${FILE}.o

 

执行结果:

 

 

  • 上面的例子中,下面两个问题需要注意

  1. 上面的例子中,主线程与子线程存在竞争条件,很可能在子线程执行之前,主线程已经执行结束而退出,从而导致整个进程的结束,因此主线程需要休眠
  2. 虽然主线程将子线程ID放入了全局变量 ntid 中,子线程依然是使用 pthread_self 函数获取自己的线程ID,这样做的原因是线程是在 pthread_create 函数返回前创建的,因此会存在一个竞争条件,就是在子线程中读取到的 ntid 可能还尚未被赋值

 






读书笔记      技术帖      linux      unix      龙潭书斋      apue      unix环境高级编程      进程      线程      pthread_create     


京ICP备15018585号