由于fork的代价太高,我们可以使用线程来使多件事情以一种非常紧密的方式同时发送。
线程:进程中多个执行路线。 是一个进程内部的一个控制序列。
1. 当进程中创建一个线程时,新的执行线程将拥有自己的栈,但与它的创建者共享全局变量、文件描述符、信号处理函数和当前目录状态。
2.为了使用线程编程:我们要包含宏_REENTRANT,他包含在pthread.h头文件中,并且编译程序时需要我们用选项-lpthread来连接线程库 。
3.可重入:可重入代码别多次调用后而仍然正常工作
4.编写多线程程序时,我们通过定义宏:_REENTRANT来告诉编译器我们需要可重入功能,这个宏的定义必须位于所有#include 语句之前。
5.创建新线程:pthread_create() ..
#include <pthread.h> int pthread_create(pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void*),void *arg);
参数1:一个表示新线程的标识符:类型pthread_t
参数2:属性(一般设为NULL即可)
参数3:要启动的函数; 这是一个返回void* ,参数为void*的函数。 因为是void*,那么表示:我们可以传递任意类型,和返回任意类型了。哈哈。牛逼!
参数4:该函数的参数。
6. 线程终止:pthread_exit() 进程终止:exit()
pthread_join () 函数在线程中的作用,等价于进程中用来收集进程信息的wait()函数。参数1:线程标识符 参数2:该线程的返回值指针的指针。
线程程序的测试与练习,我们经常使用sleep()来达到查看程序运行效果。
线程同步:
1.信号量:一段代码的看门人。适用于控制一组对象的访问,比如5根电话线中分配1条给某个线程。。。
2.互斥量:一段代码的互斥设备。适用于任意时刻只允许一个线程可以访问了共享内存。
一个程序中的多个线程试图改变一个信号量的值,系统将保证所有的操作都将依次进行。但如果是普通变量,就无法保证该变量的确定性。
3.信号量分有:1. 二进制信号量 0 1 2. 计数信号量
二进制信号量:常用来保护一段代码,使其每次只能被一个执行线程运行。我们可以使用二进制信号量。
计数信号量: 可以允许有限数目的线程执行一段指定的代码,我们可以使用计数信号量。
(计数信号量仅仅值二进制信号量的一种拓展,并不常用,他们实际调用的函数都是一样的。)
4.信号量的函数以:sem_开头。线程中使用的信号量函数有4个。 #include <semaphore.h>
1. 创建信号量函数: sem_init() ;
2. sem_wait(); 安全的使信号量减1,以原子操作的方式,不会引起冲突。该函数会在当信号量为0时,等待另一个线程+1之后,才去减一。不会减成-1.sem_trywait()非阻塞版
3. sem_post(); 安全的使信号量加1,以原子操作的方式,不会引起冲突。(信号量在这种“单个函数中能原子化地进行测试和设置”的能力使其变得非常有价值的。)
4.sem_destroy();对它的资源进行清理。(如果该信号量正别一些线程等待,那么清理会失败。 成功返回0.)
所得:线程是同步的,就在这同步的其中,为了控制先后次序,我们使用:信号量。来导致某一个线程等待,某一个线程执行着。wait() post()的使用便是在其中的先后控制。
二。线程同步的另一种方法:互斥量。pthread_mutex_t 类型。
互斥量:他允许锁住某个对象,使得每次只能有一个线程访问它。为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁他。
(用于互斥量的函数和信号量的函数非常相似) pthread_mutex_init () pthread_mutex_lock() pthread_mutex_unlock() pthread_mutex_destroy()
所得:互斥量利用的也是他的阻塞罗!! 再试图加上没有释放的锁,会导致阻塞,编程即利用了这个特性。来相互判断,相互协调同步的。相互等待呗。二进制信号量也是一样。
三。线程属性:
我们可以设置线程属性来达到更高级的线程那个。。。。
1. pthread_attr_init () 该函数初始化一个线程属性对象。
2. pthread_attr_destroy() 该函数是对属性对象进行清理和回收工作。
四。取消一个线程。
pthread_cancel() ; #include <pthread.h> int pthread_cancel(pthread_t thread);
线程可以发送取消请求给另一个线程,但是另一个线程是否取消,要看他如何处理这个取消请求。
pthread_setcancelstate(int state,int *oldstate); 这个函数可以设置:接受取消请求,也可以忽略取消请求。
pthread_setcanceltype(int type,int *oldtype); 这个可以设置取消类型:是立即呢,还是等函数都运行完了呢?