一、线程
1.线程是什么
线程是计算机中独立运行的最小单位,运行时占用很少说的系统资源。
2.线程的优点
多线程相对于多进程的优点
[1].多进程的情况下,每个进程都有自己独立的地址空间,而多线程情况下,同一进程内的线程共享进程的地址空间。因此创建一个新的进程时就要耗费时间来为其分配系统资源,而创建一个新的线程花费的时间则要少的多。
[2].在系统调度方面,由于进程地址独立而线程共享地址空间,线程间的切换速度要远远快过进程间的切换速度。
[3].在通信机制方面,进程间的数据空间相互独立,彼此通信要以专门的通信方式进行,通信时必须经过操作系统。而同一进程内的多个线程共享数据空间,一个线程的数据可以直接提供给其他线程使用,而不必经过操作系统。因此,线程间的通信更加方便和省时。
线程还具有如下优点
[4].可以提高应用程序的响应速度。
[5].可以提高多处理器效率。
[6].可以改善程序的结构。
3.线程私有的数据、
虽然线程在进程内部共享地址空间,打开文件描述符等资源,但是线程也有其私有的数据信息
[1].线程号[thread ID]:每个线程都有一个惟一的线程号一一对应。
[2].寄存器(包括程序计数器和堆栈指针)。
[3].堆栈。
[4].信号掩码。
[5].优先级。
[6].线程私有的存储空间。
二、创建线程
1.线程创建函数pthread_create
#include <pthread.h>
int pthread_create (pthrea_t *thread, pthread_attr_t *attr,
void* (*start_routine)(void *), void *arg);
参数含义
thread:该参数为一个指针,当线程创建成功时, 用来返回创建的线程ID。
attr:该参数用于指定线程的属性。
start_routine:该参数为函数指针,指向线程创建后要调用的函数。这个被线程调用的函数也称为线程函数。
arg:该参数指向传递给线程函数的参数。
线程创建实现
运行结果
2.创建线程其他系统函数
pthread_t pthread_slef(void): 获取本线程的线程ID
int pthread_equal(pthread_t thread1, pthread_t thread2):判断两个线程ID是否指向同一线程。
int pthread_once(pthread_once_t *once_control, void(*init_routine)(void)):用来保证init_routine线程函数在进程中仅执行一次
两个线程调用同一个函数,结果被调函数只被执行了一次
运行结果
3.线程属性
typedef struct
{
int detachstate; 线程的分离状态
int schedpolicy; 线程调度策略
struct sched_param schedparam; 线程的调度参数
int inheritsched; 线程的继承性
int scope; 线程间竞争CPU的范围
size_t guardsize; 警戒堆栈的大小
int stackaddr_set; 堆栈地址集
void * stackaddr; 堆栈的地址
size_t stacksize; 堆栈的大小
}pthread_attr_t;
三、线程终止
1.终止线程的两种方式
[1].通过return从线程函数返回
[2].调用函数pthread_exit()
#include <pthread.h>
void pthread_exit(void *retval);
注:在主线程中,从main函数返回或是调用了exit函数退出主线程,则整个进程将终止,此时进程中所有线程也将终止,因此在主线程中不能过早的从main函数返回;如果主线程调用pthread_exit函数,则仅仅是主线程消亡,进程不会结束,进程内的其他线程也不会终止,直到所有线程结束,进程才会结束。
2.资源释放
临界资源:在一段时间内只能被一个线程所持有。临界资源使用完毕以后要释放以便其他线程可以使用。
死锁:当一个线程终止时,如果不释放其占有的临界资源,则该资源会被认为还被已经退出的线程所使用,因而永远不会得到释放。如果一个线程在等待使用这个临界资源,他就可能无限的等待下去,形成死锁。
pthread_cleanup_push(),pthread_cleanup_pop()用于自动释放资源
#include<pthread.h>
#define pthread_cleanup_push(routine, arg) {struct _pthread_cleanup_buffer buffer;\
_pthread_cleanup_push(&buffer,(routine), (srg));
#define pthread_cleanup_pop _pthread_cleanup_pop(&buffer,(exeute));}
3.等待线程
#include<pthread.h>
int pthread_join(pthread_t th, void * thread_return);
int pthread_detach(pthread_t th);
pthread_join 的调用者将被挂起并等待th线程终止。并且被等待的线程应该处于join状态,即非DETACHED状态。DETACHED状态是指对某个线程执行pthread_detach()后其所处的状态。
一个可join的线程所占用的内存仅当有线程对其执行了pthread_join()后才会得到释放。
线程终止实例
运行结果
从运行结果可以看出pthread_join()会阻塞主线程。