本帖最后由 gjianw217 于 2016-9-25 16:07 编辑
最近项目用到了纯Linux线程,感觉有些基础知识需要巩固下,故有了linux线程重温系列。本文是第一篇,即主要了解基本概念和常用函数,最后用一小示例来验证操作。一、
线程1 Linux
进程与线程 在多任务处理中,进程和线程是免不了的,最通俗的理解就是,进程可以看成一个资源的基本单位,而线程是程序调度的基本单位,一个进程内部的线程之间共享进程获得的时间片。Linux进程创建一个新线程时,线程将拥有自己的栈(因为线程有自己的局部变量),但与它的创建者共享全局变量、文件描述符、信号句柄和当前目录状态。Linux通过fork创建子进程与创建线程之间是有区别的:fork创建出该进程的一份拷贝,这个新进程拥有自己的变量和自己的PID,它的时间调度是独立的,它的执行几乎完全独立于父进程。 使用线程最大的好处在于,改善程序结构、节省系统资源和方便任务(线程)间的通信等。
2
线程的基本函数 大多数pthread_xxx函数在失败时,遵循Unix的惯例,返回-1,如果调用成功,则返回0,关于线程,常用的函数有:
#include
int pthread_create(pthread_t *restrict thread,const pthread_attr_t *restrict attr,void *(*start_routine)(void*), void *restrict arg);
int pthread_join(pthread_t thread, void **value_ptr);
3
示例 (1)代码
(2)分析1-4行为需要包含的头文件,其中phtread.h头文件中,包含了有关pthread的相关函数定义,如pthread_create,pthread_join等。
6行为一个宏定义,表示线程的个数,宏定义一般为大写
8-15为线程回调函数,其规定为参数为一个void的指针函数,返回值为void的指针,名字用户自己定义,其中第12行是将传递过来的参数强制转换为整型类型,并通过第13行输出显示。
17行为主函数
25行为创建线程,在线程创建以后,就开始运行相关的线程函数。其中第一个参数,为线程标识符,且为指针型;第二个参数,为线程属性设置,一般为0;第三个参数,表示线程函数的起始地址,即将要执行的函数;第四个参数,代表传递给start_routine的参数;如果调用成功,则返回0,否则返回-1。
33行的pthread_join,使一个线程等待另一个线程结束,代码中如果没有pthread_join,主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。也就是说,pthread_join会等待(阻塞)由第一个参数指定的线程执行,直到其运行完成才返回。
(3)运行结果
二、
线程的同步
在Linux系统中,广义的进程或线程间通信,有很多种,在经典的《UNIX网络编程卷2进程间通信》中有详细的介绍,主要包含消息传递(管理,FIFO,消息队伍),同步(互斥量,条件变量,读写锁,文件,记录锁,信号量),共享内存,远程过程调用。
1
互斥量
互斥量是允许程序锁住某个对象,使得每次只能有一个线程访问它。为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁。常用的函数如下所示,它们都定义在pthread.h头文件中。
#include
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock (pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
2
条件变量
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线承间的同步。常用的函数如下所示,它们都定义在pthread.h头文件中。
#include
int pthread_cond_init (pthread_cond_t *cptr,const pthread_condattr_t *attr);
int pthread_cond_destroy (pthread_cond_t *cptr)
int pthread_cond_signal (pthread_cond_t *cptr)
int pthread_cond_broadcast (pthread_cond_t *cptr);
int pthread_cond_wait (pthread_cond_t *cptr,pthread_mutex_t *mptr)
int pthread_cond_timedwait (pthread_cond_t *cptr,pthread_mutex_t *mptr, const struct timespec *abstime)
3 示例代码
(1)代码
(2)分析
(3)结果
本帖最后由 gjianw217 于 2016-9-25 16:07 编辑
最近项目用到了纯Linux线程,感觉有些基础知识需要巩固下,故有了linux线程重温系列。本文是第一篇,即主要了解基本概念和常用函数,最后用一小示例来验证操作。一、
线程1 Linux
进程与线程 在多任务处理中,进程和线程是免不了的,最通俗的理解就是,进程可以看成一个资源的基本单位,而线程是程序调度的基本单位,一个进程内部的线程之间共享进程获得的时间片。Linux进程创建一个新线程时,线程将拥有自己的栈(因为线程有自己的局部变量),但与它的创建者共享全局变量、文件描述符、信号句柄和当前目录状态。Linux通过fork创建子进程与创建线程之间是有区别的:fork创建出该进程的一份拷贝,这个新进程拥有自己的变量和自己的PID,它的时间调度是独立的,它的执行几乎完全独立于父进程。 使用线程最大的好处在于,改善程序结构、节省系统资源和方便任务(线程)间的通信等。
2
线程的基本函数 大多数pthread_xxx函数在失败时,遵循Unix的惯例,返回-1,如果调用成功,则返回0,关于线程,常用的函数有:
#include
int pthread_create(pthread_t *restrict thread,const pthread_attr_t *restrict attr,void *(*start_routine)(void*), void *restrict arg);
int pthread_join(pthread_t thread, void **value_ptr);
3
示例 (1)代码
(2)分析1-4行为需要包含的头文件,其中phtread.h头文件中,包含了有关pthread的相关函数定义,如pthread_create,pthread_join等。
6行为一个宏定义,表示线程的个数,宏定义一般为大写
8-15为线程回调函数,其规定为参数为一个void的指针函数,返回值为void的指针,名字用户自己定义,其中第12行是将传递过来的参数强制转换为整型类型,并通过第13行输出显示。
17行为主函数
25行为创建线程,在线程创建以后,就开始运行相关的线程函数。其中第一个参数,为线程标识符,且为指针型;第二个参数,为线程属性设置,一般为0;第三个参数,表示线程函数的起始地址,即将要执行的函数;第四个参数,代表传递给start_routine的参数;如果调用成功,则返回0,否则返回-1。
33行的pthread_join,使一个线程等待另一个线程结束,代码中如果没有pthread_join,主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。也就是说,pthread_join会等待(阻塞)由第一个参数指定的线程执行,直到其运行完成才返回。
(3)运行结果
二、
线程的同步
在Linux系统中,广义的进程或线程间通信,有很多种,在经典的《UNIX网络编程卷2进程间通信》中有详细的介绍,主要包含消息传递(管理,FIFO,消息队伍),同步(互斥量,条件变量,读写锁,文件,记录锁,信号量),共享内存,远程过程调用。
1
互斥量
互斥量是允许程序锁住某个对象,使得每次只能有一个线程访问它。为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁。常用的函数如下所示,它们都定义在pthread.h头文件中。
#include
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock (pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
2
条件变量
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线承间的同步。常用的函数如下所示,它们都定义在pthread.h头文件中。
#include
int pthread_cond_init (pthread_cond_t *cptr,const pthread_condattr_t *attr);
int pthread_cond_destroy (pthread_cond_t *cptr)
int pthread_cond_signal (pthread_cond_t *cptr)
int pthread_cond_broadcast (pthread_cond_t *cptr);
int pthread_cond_wait (pthread_cond_t *cptr,pthread_mutex_t *mptr)
int pthread_cond_timedwait (pthread_cond_t *cptr,pthread_mutex_t *mptr, const struct timespec *abstime)
3 示例代码
(1)代码
(2)分析
(3)结果