Linux系统编程学习之《线程》
2013-08-29 21:08
106 查看
今天来总结一下Linux下的线程方面知识:
和进程相似,线程也有系统内的标识符,它的类型是pthread_t(进程是pid_t)
线程标识符只在同一进程内有效,不同进程之间可以有相同的线程标识符
1.线程标识符
我们先来看看有关线程标识符的函数
2.创建线程
Linux下创建线程比较简单,只要调用一个函数就可以了
3.终止线程
终止线程有三种终止方式:1.线程从启动例程中返回 2.线程被同一进程中的其他线程取消 3.线程自己调用pthread_exit
4.清理线程
我们知道,进程退出是可用atexit函数注册一些清理处理的函数,线程也一样可以调用一些清理函数
5.分离线程
线程有一个分离状态,使得调用pthread_join函数无法等待到它的终止状态,线程的分离状态可以在创建时确立,也可以调用函数
6.线程同步之互斥量(锁)
当有多个线程同时访问同一个变量的时候,就可能会出现数据读写不同步的问题,这就需要我们设置线程的同步机制
作为同步机制,最重要的当然就是锁了,Linux中的锁变量类型是pthread_mutex_init
7.线程同步之互斥量(锁)加锁
在互斥锁初始化后,我们需要调用一些函数才可以实现真正的加锁行为
8.线程同步之读写锁
除了上述的互斥锁外,Linux还支持读写锁,读写锁也程共享-独占锁;
当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的
读写锁的变量类型是pthread_rwlock_t,读写锁只可以用调用函数初始化方式初始化锁
9.线程同步之读写锁加锁
了解了如何创建、初始、销毁读写锁后,现在就要了解如何对对写锁进行加锁
正如前面所说,读写锁有两种加锁方式,读锁加锁或写锁加锁
10.线程同步之条件变量
条件变量是线程同步的另一种同步机制。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生
条件变量的数据类型是pthread_cond_t,有两种初始化方式
一种把PTHREAD_COND_INITIALIZER赋给静态分配的条件变量,如果是动态分配的,则调用pthread_cond_init哈数进行初始化
11.线程同步之条件变量的使用
在初始化好条件变量后,我们现在要使用它了,使用的方法是调用如下函数:
/*
* #include <pthread.h>
* int pthread_cond_wait(pthread_cond_t * restrict cond,pthread_mutex_t * restrict mutex); //对等待事件出现,再加互斥锁
* int pthread_cond_timewait(pthread_cond_t * restrict cond,
* pthread_mutex_t * restrict mutex,const struct timespec * restrict timeout); //跟上面函数类似,不过等待绝对时间(即现在时间+需等待时间)
* 两个函数成功返回0,出错返回错误编号
* -------------------------------------------
* int pthread_cond_signal(pthread_cond_t * cond); //唤醒等待该条件变量的某个线程
* int pthread_cond_broadcast(pthread_cond_t * cond); //唤醒等待该条件变量的全部线程
* -------------------------------------------
*/
和进程相似,线程也有系统内的标识符,它的类型是pthread_t(进程是pid_t)
线程标识符只在同一进程内有效,不同进程之间可以有相同的线程标识符
1.线程标识符
我们先来看看有关线程标识符的函数
/* * #include <pthread.h> * int pthread_equal(pthread_t tid1,pthread_t tid2); * 比较tid1和tid2两个线程是否是同一个线程(不同进程可有相同线程ID) * 是统一个返回非0,不是返回0 * --------------------------------------------------- * pthread_t pthread_self(void); * 返回线程的ID */
2.创建线程
Linux下创建线程比较简单,只要调用一个函数就可以了
/* * #include <pthread.h> * int pthread_create(pthread_t * restrict tidp,const pthread_attr_t * restrict attr, * void * (*start_rtn)(void),void * restrict arg); * tidp:保存新线程ID的指针 * attr:创建的线程的属性,NULL为默认属性 * (*start_rtn)(void):线程启动要要执行的函数,声明格式是:void * funcname(void * arg); * arg:线程执行函数的参数,NULL为不传参数 */
3.终止线程
终止线程有三种终止方式:1.线程从启动例程中返回 2.线程被同一进程中的其他线程取消 3.线程自己调用pthread_exit
/* * #include <pthread.h> * void pthread_exit(void * rval_ptr); * 线程自己调用,终止线程运行,直接返回,返回码保存在rval_ptr中 * -------------------------------------- * int pthread_join(pthread_t thread,void ** rval_ptr); * 同一进程中的其他线程可以调用此函数,等待指定线程结束,并获取它的返回码 * 等待过程将阻塞调用此函数的线程 * -------------------------------------- * int pthread_cancel(pthread_t tid); * 成功返回0,出错返回错误编号 * 该函数用于线程提出请求终止同一进程中的其他线程,不过被请求线程可忽略此请求 */
4.清理线程
我们知道,进程退出是可用atexit函数注册一些清理处理的函数,线程也一样可以调用一些清理函数
/* * #include <pthread.h> * void pthread_cleanup_push(void (*rtn)(void *),void * arg); * (*rtn)(void *):清理处理函数,定义格式:void funcname(void * arg); * arg:传给清理处理函数的参数 * ----------------------------------- * void pthread_cleanup_pop(int execute); * execute:非0则执行清理函数,0则不执行 * ----------------------------------- * 上述两个函数要在作用域{}内配对使用,否则可能会出错 */
5.分离线程
线程有一个分离状态,使得调用pthread_join函数无法等待到它的终止状态,线程的分离状态可以在创建时确立,也可以调用函数
/* * #include <pthread.h> * int pthread_detach(pthread_t tid); * 成功返回0,出错返回错误编号 * 该函数使线程进入分离状态 */
6.线程同步之互斥量(锁)
当有多个线程同时访问同一个变量的时候,就可能会出现数据读写不同步的问题,这就需要我们设置线程的同步机制
作为同步机制,最重要的当然就是锁了,Linux中的锁变量类型是pthread_mutex_init
/* * #include <pthread.h> * int pthread_mutex_init(pthread_mutex_t * restrict mutex,const pthread_mutexattr_t * restrict attr); * ---------------------------------------- * mutex:锁变量 * attr:锁的属性,NULL为默认属性 * ---------------------------------------- * int pthread_mutex_destroy(pthread_mutex_t * mutex); * ---------------------------------------- * 要销毁的锁变量 * ---------------------------------------- * 两个函数成功返回0,出错返回错误编号 * ---------------------------------------- * 锁的变量类型是pthread_mutex_t,要使用锁之前,先要对其进行初始化 * 可以把它设置为常量PTHREAD_MUTEX_INITALIZER(只对静态分配的互斥锁有效) * 其他的就要调用pthread_mutex_init函数 * 如果是动态分配的互斥锁(如调用malloc函数) * 则在释放内存前需要调用pthread_mutex_destroy函数销毁 * ---------------------------------------- */
7.线程同步之互斥量(锁)加锁
在互斥锁初始化后,我们需要调用一些函数才可以实现真正的加锁行为
/* * #include <pthread.h> * int pthread_mutex_lock(pthread_mutex_t * mutex); * int pthread_mutex_trylock(pthread_mutex_t * mutex); * int pthread_mutex_unlock(pthread_mutex_t * mutex); * --------------------------------- * 三个函数成功返回0,出错返回错误编号 * mutex是欲操作的锁变量 * pthread_mutex_lock对于mutex未加锁,则直接加锁进入下一步骤 * 如果mutex已被加锁,则线程会被阻塞,一致等待锁被释放了才进入锁 * pthread_mutex_trylock对于mutex未枷锁,则直接加锁进入下一步骤,返回0 * 如果mutex已被加锁,则线程不会被阻塞,加锁失败,返回EBUSY * 无论哪种加锁方式,释放锁同一调用pthread_mutex_unlock函数 * --------------------------------- */
8.线程同步之读写锁
除了上述的互斥锁外,Linux还支持读写锁,读写锁也程共享-独占锁;
当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的
读写锁的变量类型是pthread_rwlock_t,读写锁只可以用调用函数初始化方式初始化锁
/* * #include <pthread.h> * int pthread_rwlock_init(pthread_rwlock_t * restrict rwlock,const pthread_rwlockattr_t * restrict attr); * ---------------------------------------- * rwlock:读写锁变量 * attr:读写锁属性,NULL为默认属性 * ---------------------------------------- * int pthread_rwlock_destroy(pthread_rwlock_t * rwlock); //rwlock为欲销毁的读写锁变量 * ---------------------------------------- * 两个函数成功返回0,粗错返回错误编号 */
9.线程同步之读写锁加锁
了解了如何创建、初始、销毁读写锁后,现在就要了解如何对对写锁进行加锁
正如前面所说,读写锁有两种加锁方式,读锁加锁或写锁加锁
/* * #include <pthread.h> * int pthread_rwlock_rdlock(pthread_rwlock_t * rwlock); //加读锁 * int pthread_rwlock_wrlock(pthread_rwlock_t * rwlock); //加写锁 * int pthread_rwlock_unlock(pthread_rwlock_t * rwlock); //解除锁 * 所有函数:成功返回0,出错返回错误编号 * ------------------------------------------ * 加读锁时,如果没有被加写锁,则允许进入,否则阻塞 * 加写锁时,要当前锁没有任何锁状态才进入,否则阻塞等待 * 读锁写锁使用完毕后都要调用unlock函数解除锁状态 * ------------------------------------------ * int pthread_rwlock_tryrdlock(pthread_rwlock_t * rwlock); //尝试加读锁 * int pthread_rwlock_tryrwlock(pthread_rwlock_t * rwlock); //尝试加写锁 * ------------------------------------------ * 如果成功获取锁,则进入,函数返回0 * 否则,返回出错EBUSY,但并不阻塞等待 */
10.线程同步之条件变量
条件变量是线程同步的另一种同步机制。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生
条件变量的数据类型是pthread_cond_t,有两种初始化方式
一种把PTHREAD_COND_INITIALIZER赋给静态分配的条件变量,如果是动态分配的,则调用pthread_cond_init哈数进行初始化
/* * #include <pthread.h> * int pthread_cond_init(pthread_cond_t * restrict cond,pthread_condaddr_t * restrict attr); * int pthread_cond_destroy(pthread_cond_t * cond); //cond为条件变量 * 两个函数:成功返回0,出错返回错误编号 * 在init函数中,如果要传递NULL给attr,则创建默认的条件变量 */
11.线程同步之条件变量的使用
在初始化好条件变量后,我们现在要使用它了,使用的方法是调用如下函数:
/*
* #include <pthread.h>
* int pthread_cond_wait(pthread_cond_t * restrict cond,pthread_mutex_t * restrict mutex); //对等待事件出现,再加互斥锁
* int pthread_cond_timewait(pthread_cond_t * restrict cond,
* pthread_mutex_t * restrict mutex,const struct timespec * restrict timeout); //跟上面函数类似,不过等待绝对时间(即现在时间+需等待时间)
* 两个函数成功返回0,出错返回错误编号
* -------------------------------------------
* int pthread_cond_signal(pthread_cond_t * cond); //唤醒等待该条件变量的某个线程
* int pthread_cond_broadcast(pthread_cond_t * cond); //唤醒等待该条件变量的全部线程
* -------------------------------------------
*/
相关文章推荐
- 线程锁定
- 辅助线程安全退出
- Java集合HashSet-ArrayList-HashMap的线程同步控制方法和区别
- 进程与线程的一个简单解释
- java多线程之线程锁
- 多线程 学习笔记<1> 线程建立
- 从锁的角度理解线程
- 进程与线程的区别(转)
- 多线程-线程锁
- 进程和线程关系及区别
- java面试题3 线程 Thread类
- Java 中线程(二)
- 创建并运行一个java线程方法介绍
- Linux进程管理 (篇外)内核线程简要介绍
- Delphi中网络实现线程变量同步
- java线程同步,必须知道的
- 谈.Net委托与线程——解决窗体假死
- 线程中CreateEvent和SetEvent及WaitForSingleObject的用法
- 子线程调用Toast报Can't create handler inside thread that has not called Looper.prepare() 错误
- OSG创建渲染线程的过程