概念
由于进程在切换时系统开销大,因此很多操作系统引入了轻量级进程LWP,同一进程中的线程共享相同地址空间,Linux不区分进程、线程。
线程特点
进程有独立的地址空间,Linux为每个进程创建task_struct,每个进程都参与内核调度,互不影响。而线程指的是共享相同地址空间的多个任务,注意Linux不区分进程、线程。
一个进程中的多个线程共享以下资源:
① 可执行的指令
② 静态数据
③ 进程中打开的文件描述符
④ 当前工作目录
⑤ 用户ID
⑥ 用户组ID
每个线程私有的资源包括:
① 线程ID (TID)
② PC(程序计数器)和相关寄存器
③ 堆栈
④ 错误号 (errno)
⑤ 优先级
⑥ 执行状态和属性
Linux线程库
3.1 pthread线程库中提供了如下基本操作
创建线程
回收线程
结束线程
3.2 同步和互斥机制
信号量
互斥锁
4. 线程函数
4.1 线程创建 – pthread_create
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*routine)(void *), void *arg);
成功返回0,失败时返回错误码, thread 线程对象, attr 线程属性,NULL代表默认属性
routine 线程执行的函数, arg 传递给routine的参数 ,参数是void * ,注意传递参数格式。
4.2 线程结束 – pthread_exit
#include <pthread.h>
void pthread_exit(void *retval);
结束当前线程, retval可被其他线程通过pthread_join获取, 线程私有资源被释放。
4.3 线程查看tid函数
#include <pthread.h>
pthread_t pthread_self(void); // 查看自己的TID
4.4 线程查看命令
ps -eLf
4.5 线程回收 – pthread_join
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
对于一个默认属性的线程 A 来说,线程占用的资源并不会因为执行结束而得到释放,需要进行线程回收。 成功返回0,失败时返回错误码。 thread 要回收的线程对象, 调用线程阻塞直到thread结束。
*retval 接收线程thread的返回值。
例1
Testhread 打印信息后5s退出线程,并且pthread_join()回收线程资源。注意此例中第19行和第6行直接的子进程的参数传递。通过传递&i的地址,子线程中强制类型转换i的地址指针后再取地址中的值。
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
void *Testhread(void *arg) {
printf("This is Testhread arg = %d ...\n", *(int*)arg);
sleep(5);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
pthread_t tid;
int i = 3;
int ret;
void *retv;
tid = pthread_create(&tid, NULL, Testhread,&i);
ret = pthread_join(tid,&retv);
while (1) {
sleep(1);
}
return 0;
4.6 线程分离pthead_detach
int pthread_detach(pthread_t thread); 成功:0;失败:错误号
指定该状态,线程主动与主控线程断开关系。线程结束后(不会产生僵尸线程)
pthread_attr_t attr; /*通过线程属性来设置游离态(分离态)*/
设置线程属性为分离
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
例 2
创建100个线程,线程创建后10s执行pthread_detch与主进程脱离关系并且退出线程。
include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *Testhread(void *argv)
{
printf("This is %d thread...\n", *(int *)argv);
sleep(10);
pthread_detach(pthread_self());
printf("%d is exit ..\n",(int)pthread_self());
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
pthread_t tid[100];
int ret;
int i;
for (i = 0; i<100; i++)
{
ret = pthread_create(&tid[i], NULL, Testhread,&i);
//pthread_detach(tid[i]);
sleep(1);
}
while (1) {
sleep(1);
}
return 0;
}
4.7 取消一个线程
int pthread_cancel(pthread_t thread); 杀死一个线程
void pthread_testcancel(void);
int pthread_setcancelstate(int state, int *oldstate);
PTHREAD_CANCEL_ENABLE
PTHREAD_CANCEL_DISABLE
int pthread_setcanceltype(int type, int *oldtype);
PTHREAD_CANCEL_DEFERRED
PTHREAD_CANCEL_ASYNCHRONOUS
4.8 线程的清理
void pthread_cleanup_push(void (*routine) (void *), void *arg)
void pthread_cleanup_pop(int execute)