一、线程
1、线程:进程内部的一条执行路径或者执行序列
main() thread_fun()
{ {
//主线程 //子线程
} }
2.线程出现的情况
(1)程序需要同时做到2件及以上的事情的时候(并发运行)
(2)使用多处理器
3线程创建成功和主函数执行是并发的
(1)线程:一个轻量级的进程
(2)主线程pid为进程的pid
(3)可以使用命令ps -elf 显示进程内部的线程的id
(4)线程和进程的实现是一样的,只是线程的进程和父进程在linux中共享资源
4.调试线程
(1)gdb
(2)strace//跟踪命令(用系统调用)
(3)Ltrace//跟踪程序(用库函数实现)
5.线程同步的实现(解决并发运行的时候,多处理器的情况下会遇到两个或者多个线程同时访问同一个变量的情况)
(1)信号量:定义信号量,p,v操作,销毁信号量
(2)互斥锁:用之前加锁,用完后解锁,其他线程不可以随意加/解其他线程的锁
(3)条件变量:满足一条件,一个程序才可执行
A.初始化条件变量:pthread_cond_init();
B.条件不满足阻塞:pthread_cond_wait();
C.唤醒条件变量上等待的线程:pthread_cond_signal();
D.唤醒所有在条件变量上等待的线程:pthread_cond_broadcast();
E.销毁:pthread_cond_destory();
F.定义:pthread_cond_t cond();
G.使用线程安全函数(可重入方法)
(4)读写锁//可二读,不可二写
A.初始化pthread_rwlock_init();
B.加读锁rdlock();
C.加写锁wrlock();
D.释放unlock();
6.线程安全
(1)经过同步的线程是安全的
(2)使用线程安全函数
eg:strtok()函数的线程安全函数是strtok_r()
多线程容易产生问题,会修改strtok中的静态变量(strtok()中的静态变量来记
录分割后的位置,从而在第二次分隔使用strtok()函数时传NULL)
7.在原子操作中,加锁和解锁的是实现过程//利用cpu的特殊指令来实现
8.fork()和多线程:
多线程程序fork()函数后,子进程只启用fork()所在的一条执行路径
9.fork()后,父子进程哪些是共享的,哪些是分开的
(1)共享的资源:
打开的文件
实际用户ID、实际组ID、有效用户ID、有效组ID
添加组ID
进程组ID
对话期ID
控制终端
设置-用户-ID标志和设置-组-ID标志
当前工作目录
根目录
文件方式创建屏蔽字
信号屏蔽和排列
对任一打开文件描述符的在执行时关闭标志
环境
连接的共享存储段(共享内存)
资源限制
(2)独立的资源:
fork的返回值
进程ID
不同的父进程ID
子进程的tms_utime,tms_stime,tms_cutime以及tms_ustime设置为0
父进程设置的锁,子进程不继承
子进程的未决告警被清除
子进程的未决信号集设置为空集
10.父进程创建的互斥锁fork后,给子进程创建复制一份锁的状态是fork那一刻
父进程中锁的状态,父子进程中的锁不是同一把
//解决方案:在fork()之前判断是否有加锁,无加锁时在fork()
pthread_atfork() :函数用来确保fork()调用父子进程都拥有一个清楚的锁的状态
11.线程可以设置属性,并且一个线程具有结束另一个线程的权限需要调用函数
pthread_exit():使线程退出
pthread_join使一个线程等待另一个线程结束
12.linux中多线程的调试
(1)info threads //显示线程
(2)thread id //切换到另一个线程
(3)set schedualer_locking [ off / on /step ] //设置线程运行的方式
A.off 不锁定任何线程,任何线程均可运行,默认值
B.on 只有当前被调试程序会执行。
C.step在单步的时候,除了next过一个函数的情况以外,只有当前线程会执行。
13.在主函数之前打印一行信息的做法
(1)在c++中通过构造函数
(2)在c语言中:
A:通过宏定义或者定义的结构体中;
B:可以在想运行的函数的声明(注意这里是声明)之后加上一句 “__attribute__((constructor))”来实现;同理,在想运行的函数的声明(要是声明)之后加上一句“__attribute__((destructor))”来实现;
C:atexit 函数是标准 C 新增的;
void fn1(void), fn2(void), fn3(void), fn4(void);
int main()
{
// 注册需要在 main 函数结束后执行的函数.
atexit(fn1); atexit(fn2); atexit(fn3); atexit(fn4);
}