linux学习笔记之线程
线程同步机制:http://www.cnblogs.com/zheng39562/p/4270019.html
一、基础知识
1:基础知识。
1,线程需要的信息有:线程ID,寄存器,栈,调度优先级和策略,信号屏蔽字,errno变量和线程私有数据。
2,进程的所有信息对所有线程都是共享的。
3,是否支持有多线程有以下两种方式测试:
1)编译时确定:#ifdef _POSIX_THREADS
2)运行时确定:sysconf函数调用 _SC_THREADS 常用。
4,线程ID。
1)一个进程中,线程ID具有唯一性。线程ID依赖与进程后,才有意义。
2)线程ID表示类型:pthread_t类型
5,变量增量操作的步骤:
1)变量值从 内存单元 读入 寄存器。
2)寄存器中对变量进行修改。
3)将变量值 写回 内存单元
4)所以,多个线程试图同时修改同一变量时,需要同步。
6,进程资源和线程的关系:
1)每个线程都有自己的信号屏蔽字。但,信号处理是所有线程共享的。所以,线程对信号的处理会影响所有线程。
2)闹钟定时是进程资源。所有线程共享使用。
3)pread / pwrite 函数在多线程读写比较适用。因为其可以保存多个线程的读写偏移量,从而保证不会被覆盖。
2:线程创建和终止。
1,线程创建。
1)并不能确定哪个线程先运行(和子进程创建类似)。
2)创建函数create失败后,通常会返回错误码。
2,线程终止。
1)任意线程调用 exit, _Exit, _exit函数都会使进程终止。(所以不可以使用此方式终止单个线程)
2)从启动例程返回。返回值时线程退出码。
3)可以被同进程中的其他线程取消。
4)线程调用pthread_exit函数。
3:线程的数据和安全
1,线程安全:一个函数在相同时间点可以被多个线程安全地调用。
1)当一个函数是可重入时,那就是线程安全的。
2)异步信号安全。
2,可重入函数。
1)当处理信号中断时,部分函数可能更改信息,导致中断处理结束后,无法正确的从中断点继续执行程序(信息错位)。
2)可重入函数保证再中断期间调用这些函数,不会导致信息错位。
3)可重入函数又被称为异步信号安全的函数。
3,线程私有数据:具体操作见函数。
5:进程和线程功能/函数对应表
进程原语 | 线程原语 | 描述 |
fork |
pthread_create | 创建新的控制流 |
exit | pthread_exit | 从先有控制流中退出 |
waitpid | pthread_join | 从控制流中得到退出状态 |
atexit | pthread_cancel_push | 注册在退出控制流时的调用的函数 |
getpid | pthread_self | 获取控制流的ID |
abort | pthread_cancel | 请求控制流的非正常退出。 |
二、相关函数。
1:线程操作函数。
比较线程ID大小。
int pthread_equal( pthread_t tid1, pthread_t tid2 )
获取自身线程ID。
pthread_t pthread_self( void );
创建线程。
int pthread_create( pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 1 参数arg用于定制各种不同的线程属性
线程终止。
void pthread_exit( void *rval_ptr );
获得线程退出状态。
int pthread_join( pthread_t thread, void **rval_ptr );
// 1 参数rval_ptr包含返回码。
取消其他线程(同进程中使用)
int pthread_cancel( pthread_t tid );
// 1 仅仅提出请求。并不强制终止。
线程清理处理程序(类似进程的atexit)。
void pthread_cleanup_push( void (*rtn)(void *), void *arg);
void pthread_cleanup_pop( int execute );
// 1 参数execute=0时,清理函数将不被调用。
// 2 每次调用pop函数时,都出删除上一个push的清理程序。
// 3 这些函数被实现为宏。需要注意{}等匹配。
// 4 清理程序的注册和执行顺序相反。
分离线程。
int pthread_detach( pthread_t tid );
清除子进程的锁
int pthread_atfork( void (*prepare)(void), void (*parent)(void), void (*child)(void) );
// 1 注册和执行顺序相反。
上述函数中。部分无类型指针,可以传递的值有很多,甚至可以时一个结构体。
2,线程属性 相关函数。
线程属性 初始化 和 类析构函数
int pthread_attr_init( pthread_attr_t *attr );
int pthread_attr_destroy( pthread_attr_t *attr );
获取/设置 分离状态。
int pthread_attr_getdetachstats( const pthread_attr_t *restrict attr, int *detachstate );
int pthread_attr_setdetachstats( pthread_attr_t *attr, int *detachstate );
// 1 参数detachstate只有两个值:PTHREAD_CREATE_ DETACHED/JOINABLE.
获取/设置 线程栈属性 stackaddr。
int pthread_attr_getstack( const pthread_attr_t *restrict attr, void **restrict stackaddr, size_t *restrict stacksize );
int pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize );
// 1 stackaddr线程属性定义为栈的最低内存地址。是起始位置,还是结尾位置取决于栈的发展方向。通常是结尾(栈由高向低)
获取/设置 栈大小属性 stacksize。
int pthread_attr_getstacksize( const pthread_attr_t *restrict attr, size_t *restrict stacksize );
int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize );
获取/设置 线程栈末尾缓冲区大小 guardsize。
int pthread_attr_getguardsize( const pthread_attr_t *restrict attr, size_t *restrict guardsize );
int pthread_attr_setguardsize( pthread_attr_t *attr, size_t guardsize );
3:线程私有数据。
创建一个键
int pthread_key_create( pthread_key_t *keyp, void (*destructor)(void *));
// 1 可以指定一个析构函数(第二个参数)
// 2 每个线程的键的独立的:即相同的KEY在不同线程中表示不同的数据。
取消一个键和特定线程的关联。
int pthread_key_delete( pthread_key_t key );
// 1 不激活关联的析构函数。
使一个键只被调用一次:使不同线程拥有不同的键。
int pthread_once( pthread_once_t *initflag, void (*initfn)(void));
获取/设置 键内数据。
void *pthread_getspecific( pthread_key_t key );
int pthread_setspecific( pthread_key_t key , const void *value );
4:特殊线程属性:可取消状态 和 可取消类型。
设置 可取消状态
int pthread_setcancelstate( int state, int *oldstate );
// 1 取消状态有两种: PTHREAD_CANCEL_ ENABLE/DISABLE
设置 自己的取消点。
void pthread_testcancel( void );
// 1 取消状态作用:取消请求发出后,会在下一个取消点进行取消操作(个人理解退出线程)。
修改取消类型。
int pthread_setcanceltype( int type, int *oldtype )
5:线程和信号
线程阻止信号发送
int pthread_sigmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
等待信号。
int sigwait( const sigset_t *restrict set, int *restrict signop );
// 1 参数set指定线程等待的信号集。
// 2 参数signop 包含发送信号的数量。
// 3 在使用函数前,必须先阻塞它等待的信号。(参数一)
// 4 函数在执行时,会取消信号集的阻塞状态。
发送信号给线程。
int pthread_kill( pthread_t thread, int signo );
// 1 参数signo传递0,可以检查线程是否存在
三、
最新文章
- Cookie和Session的那些事儿
- php中的cookie用法
- [汇编] C语言中嵌入汇编
- Vim 练级攻略
- linux死锁检测的一种思路【转】
- C++11新特性:Lambda函数(匿名函数)
- VC2008下CRichEditView加载RichEdit4.1版本(还有一些类似的文章)
- Asp.net - The type or namespace name 'App_Code' does not exist in the namespace 'xxx' (are you missing an assembly reference?)
- QT绘制系统简介
- mysql常用操作命令
- 手动安装Nginx
- .NET ClrProfiler ILRewrite 商业级APM原理
- MySQL分布式事物(XA事物)的使用
- codeforces618B
- ML.NET 0.10特性简介
- 阿里云服务器搭建FTP
- Linux性能测试分析命令_top
- 30个你 “ 不可能全部会做 ” 的javascript题目-答案解释
- Spring Boot 概述
- 在spring boot上基于maven使用redis——批量匹配并删除 (二)