说明:
本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
QQ 群 号:513683159 【相互学习】
内容来源:
《Linux系统编程》、《Linux网络编程》
目录:
一、线程(thread)的相关认识
(1)线程引入的原因及目的:
多线程引入的原因:
为共享存储环境下有效地开发应用程序细粒度并行度。
为节省资源而可在同一进程中共享资源的一个执行单位。
多线程的目的:
1.应付各种并发性问题。(被动)
2.加快任务处理速度。(主动)
(2)线程的描述:
线程是进程的一个实体,是被系统独立调度和分派的基本单位,是进程中活动的对象。
线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源(如:程序计数器、一组寄存器、栈),但可与同属进程的其他线程共享进程所拥有的的全部资源。
总结:进程是资源分配和保护的实体。线程是被调度执行的基本单位。
PS:
Linux内核来说,线程被当作与其他进程共享某些资源的进程,每个线程都拥有唯一隶属于自己的task_struct
(3)线程含有的信息:
1️⃣包含表示进程内执行环境必须的信息:
线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno
变量、线程私有数据。
2️⃣包含进程所有信息(该进程的额所有线程共享):
可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。
(4)线程的相关描述
(1)线程ID(pthread_t
):非负整数,只在所属进程环境中有效。
(2)线程终止方式:
1️⃣调用pthread_exit(3)
并指定退出状态值,该值可被调用pthread_join(3)
的进程中的其他线程使用。
2️⃣从start_routine()
启动例程中返回。这相当于用return
语句中提供的值调用pthread_exit(3)
。
3️⃣可被同一进程中的其他线程取消(参见pthread_cancel(3)
)。
4️⃣进程中的任何线程调用exit()/_Exit()/_exit()
或主线程执行main()
返回。这将导致进程中所有线程的终止。
(3)
(5)线程同步
(1)互斥量(确保同一时间只有一个线程访问数据)
数据类型:pthread_mutex_t
,
状态:锁住状态 / 不加锁状态
概念:本质是一把锁,访问共享资源前对互斥量进行加锁,访问完成后释放互斥量上的锁。加锁后,任何试图再次加锁线程会被阻塞直到当前线程释放该锁。若存在多个线程被阻塞则所有线程都变成可运行状态,第一个运行状态线程进行加锁,其他仍被锁住。
(2)死锁:线程试图对同一互斥量加锁两次,则陷入死锁状态。
不明显死锁状态:使用多互斥量时,允许线程1一直占有第一个互斥量,并试图锁住第二个互斥量时处于阻塞状态,但第二个互斥量的线程2也试图锁住第一个互斥量。
(3)读写锁:与互斥量类似,但允许更高并行性。
也叫共享-独占锁,读共享,写独占。
状态:读模式下加锁状态/ 写模式下加锁状态 / 不加锁状态
一次只有一个线程可占有写模式的读写锁,但多个线程可同时占有读模式读写锁。
写加锁状态时,该锁解锁前没所有试图对这个锁加锁的线程都会被阻塞。
读加锁状态时,所有试图读模式对他加锁的线程可得到访问权,但想写模式加锁的必须阻塞直到所有线程释放读锁。
适用范围:对数据结构读的次数远大于写的情况。
(4)条件变量:给多个线程提供一个会合的场所
数据类型:pthread_cond_t
,
概念:条件变量与互斥量一起使用使用时,允许线程以无竞争的方式等待特定的条件发生。
条件变量本身由互斥量保护,线程在改变条件状态前必须先锁住互斥量,其他线程在获得互斥量之前不会察觉到这种改变,因为必须锁定互斥量以后才能计算条件。
(6)线程私有数据(特定数据)
一种存储和查询与某个线程相关数据的机制。
目的:每个线程都可独立访问数据副本,无需担心与其他线程同步问题。
标识符:键。(线程ID并不保证小而连续的整数,故使用键)
获取对线程私有数据的访问权.
(7)线程信号
①每个线程都有自己的信号屏蔽字,但信号的处理是进程中所有线程共享的,即:
单个线程可阻止某些信号,但当线程修改与某个信号相关处理行为后,所有线程都共享该处理行为的改变。
②进程中信号是递送到单个线程的。
二、线程函数
(1)线程基本操作函数
pthread_equal()——比较线程ID
pthread_self()——获取调用线程的ID
pthread_create()——创建线程
pthread_exit() ——结束线程
pthread_join() ——阻塞线程
pthread_cancel()——取消线程
pthread_detach()——分离线程
pthread_cleanup_push()——例程压栈
pthread_cleanup_pop()——例程出栈
(2)线程同步函数
(一)互斥量(互斥锁)
pthread_mutex_init()——初始化互斥锁
pthread_mutex_destroy()——销毁互斥锁
pthread_mutex_lock()——对互斥量加锁
pthread_mutex_trylock()——对互斥量尝试加锁
pthread_mutex_unlock()——对互斥量解锁
(二)读写锁
pthread_rwlock_init()——初始化读写锁
pthread_rwlock_destroy()——销毁读写锁
pthread_rwlock_rdlock()——读模式加锁
pthread_rwlock_tryrdlock()——读模式尝试加锁
pthread_rwlock_wrlock()——写模式加锁
pthread_rwlock_trywrlock()——写模式尝试加锁
pthread_rwlock_unlock()——解锁读写锁对象
(三)条件变量
pthread_cond_init()——初始化条件变量
pthread_cond_destroy()——销毁条件变量
pthread_cond_wait()——有条件的等待
pthread_cond_timedwait()——有条件的等待
pthread_cond_signal()——信号一个条件
pthread_cond_broadcast()——广播一个条件
(3)线程控制
(一)线程属性
pthread_attr_init()——初始化线程属性对象
pthread_attr_destroy()——销毁线程属性对象
pthread_attr_getdetachstate()——在线程属性对象中获取分离状态属性
pthread_attr_setdetachstate()——在线程属性对象中设置分离状态属性
pthread_attr_getstack()——在线程属性对象中获取堆栈属性
pthread_attr_setstack()——在线程属性对象中设置堆栈属性
pthread_attr_getstacksize()——在线程属性对象中获取堆栈大小属性
pthread_attr_setstacksize()——在线程属性对象中设置堆栈大小属性
pthread_attr_getguardsize()——在线程属性对象中获取保护大小属性
pthread_attr_setguardsize()——在线程属性对象中设置保护大小属性
pthread_getconcurrency()——获取并发级别
pthread_setconcurrency()——设置并发级别
(二)同步属性
1.互斥量
pthread_mutexattr_init()——初始化互斥属性对象
pthread_mutexattr_destroy()——销毁互斥属性对象
pthread_mutexattr_getpshared()——获取进程共享属性
pthread_mutexattr_setpshared()——设置进程共享属性
pthread_mutexattr_gettype()——获取互斥类型属性
pthread_mutexattr_settype()——设置互斥类型属性
2.读写锁
pthread_rwlockattr_init()——初始化一个读写锁属性对象
pthread_rwlockattr_destroy()——销毁一个读写锁属性对象
pthread_rwlockattr_getpshared()——获取读写锁属性对象的进程共享属性
pthread_rwlockattr_setpshared()——设置读写锁属性对象的进程共享属性
3.条件变量
pthread_condattr_init()——初始化条件变量属性对象
pthread_condattr_destroy()——销毁条件变量属性对象
pthread_condattr_getpshared()——获取进程共享属性的值。
pthread_condattr_setpshared()——设置进程共享属性。
(4)私有数据
pthread_key_create ()——创建线程键:
pthread_key_delete ()——删除线程键
pthread_once()——动态包初始化
pthread_getspecific()——获取线程私有数据地址:
pthread_setspecific ()——设置 线程特定数据
(5)取消选项
pthread_setcancelstate()——设置取消状态
pthread_setcanceltype()——设置取消类型
pthread_testcancel()——请求交付任何未决的取消请求
(6)线程和信号
pthread_sigmask()——检查并更换屏蔽信号
sigwait()——等待信号
pthread_kill()——向线程发送一个信号
(7)线程和fork()
pthread_atfork()——注册叉处理程序
三、进程与线程的区别与联系
(1)区别:
项目 | 进程 | 线程 |
---|---|---|
资源分配 | OS资源分配的最小单位 | 除CPU资源外,不分配独立资源,所需资源需共享 |
系统调度 | OS系统调度最小单位 | |
并行完成功能 | 资源分享方式有限 | 多线程之间,内存、变量等资源可共享 |
控制表 | 进程控制表PCB | 线程控制表TCB |
ID编号 | 进程ID | 线程ID 只在所属进程内起作用 |
(2)联系:
①线程属于进程的一部分,
若无线程分配,则进程为单线程的。
若有线程分配,则进程为多线程的。
②同一进程下的所有线程:
共享同一地址空间、文件描述符、栈以及进程相关属性。
③进程原语与线程原语的比较:
进程原语 | 线程原语 | 描述 |
---|---|---|
fork | pthread_create | 创建新的控制流 |
exit | pthread_exit | 从现有控制流中退出 |
waitpid | pthread_join | 从控制流中得到退出状态 |
atexit | pthread_cleanup_push | 注册在退出控制流时调用的函数 |
getpid | pthread_self | 获取控制流ID |
abort | pthread_cancel | 请求控制流的非正常退出 |