1. 线程概念
1.1 Linux进程与线程
Linux进程创建一个新线程时,线程将拥有自己的栈(因为线程有自己的局部变量),但与它的创建者共享全局变量、文件描述符、信号句柄和当前目录状态。
Linux通过fork创建子进程与创建线程之间是有区别的:fork创建出该进程的一份拷贝,这个新进程拥有自己的变量和自己的PID,它的时间调度是独立的,它的执行几乎完全独立于父进程。
进程可以看成一个资源的基本单位,而线程是程序调度的基本单位,一个进程内部的线程之间共享进程获得的时间片。
2. 函数学习
#include <stdlib.h>
#include <pthread.h>
int main(void)
{
pthread_t thread_id;
/*obtain ID of the calling thread*/
thread_id = pthread_self();
printf("Thread ID: %lu \n",thread_id);
if(pthread_equal(thread_id,pthread_self()))
{
printf("Equal!\n");
}
else
{
printf("Not equal!\n");
}
return 0;
}
执行结果:
Thread ID: 0
Equal!
pthread_create 创建一个新线程 | ||
所需头文件 | #include <pthread.h> | |
函数说明 | 在函数调用时创建一个新线程 | |
函数原型 | int pthread_create(pthread_t *thread,const pthread_attr_t *attr, void *(*start_routine) (void*),void *arg); | |
函数传入值 | thread | 线程标识符 |
attr | 线程属性设置(通常取值为NULL) | |
start_routine | 线程函数的起始地址,是一个指向void的在指针作为参数和返回值的函数指针 | |
arg | 传递给start_routine的参数 | |
| ||
| ||
函数返回值 | 成功:0 | |
错误:返回错误码 | ||
错误代码 | EAGAIN:创建其他线程时资源不足,或者遇到系统限制线程数. EINVAL:在attr的设置无效 EPERM:没有权限在attr设置调度规则和参数指定 |
pthread_join函数原型:
pthread_join 等待线程 | ||
所需头文件 | #include <pthread.h> | |
函数说明 | 调用该函数的线程将挂起,等待 thread 所表示的线程的结束. | |
函数原型 | int pthread_join(pthread_t thread, void ** retval) | |
函数传入值 | thread | 等待线程的标识符 |
| ||
retval | 用户定义的指针,用来存储被等待线程结束时的返回值(不为NULL时) | |
| ||
| ||
函数返回值 | 成功:0 | |
出错:返回错误码 | ||
| ||
错误代码 | EDEADLK:检测到一个死锁,或者thread指定为调用线程 EINVAL: thread 不是一个等待线程
EINVAL: 其他线程正在等待连接这个线程
ESRCH: 没有找到thread的线程ID
|
等待线程
•由于一个进程中的多个线程是共享数据段的,通常在线程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放
•pthread_join()函数
pthread_exit函数原型:
pthread_exit 终止线程调用 | ||
所需头文件 | #include <pthread.h> | |
函数说明 | 终止线程调用 | |
函数原型 | void pthread_exit(void *retval) | |
函数传入值 | retval | 线程结束时的返回值,可由其它函数如pthread_join()来获取 |
| ||
| ||
| ||
函数返回值 | 无 | |
| ||
错误代码 | 这个函数总是成功 |
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *thrd_func1(void *arg);
void *thrd_func2(void *arg);
pthread_t tid1,tid2;
int main(void)
{
/*create thread "tid1",thread function "thrd_func1"*/
if(pthread_create(&tid1,NULL,thrd_func1,NULL))
{
printf("Create thread 1 error!\n");
exit(1);
}
/*create thread "tid2",thread function "thrd_func2"*/
if(pthread_create(&tid2,NULL,thrd_func2,NULL))
{
printf("Create thread 2 error!\n");
exit(1);
}
/*wait thread "tid1" exit*/
if(pthread_join(tid1,NULL)!=0)
{
printf("Join thread 1 errot!\n");
exit(1);
}
else
{
printf("Thread 1 Joined!\n");
}
/*wait thread "tid2" exit*/
if(pthread_join(tid2,NULL)!=0)
{
printf("Join thread 2 errot!\n");
exit(1);
}
else
{
printf("Thread 2 Joined!\n");
}
return 0;
}
void *thrd_func1(void *arg)
{
/*set other threads can 'cancel' current thread */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
while(1)
{
printf("Thread 1 is running!\n");
sleep(1);
}
pthread_exit((void*)0);
}
void *thrd_func2(void *arg)
{
printf("Thread 2 is running\n");
sleep(5);
/*tid1 send 'cancel'to tid1 */
if(pthread_cancel(tid1)==0)
printf("Send Cancel cmd to Thread 1. \n");
}
pthread_exit((void *)0);
}
编译:
gcc pthread_create.c -lpthread -o pthread_create