线程的概念:线程是进程内部的一条执行路径(或者序列)。一个只有一条执行路径的进程是一个单线程。线程就是进程执行的一条通路;
从操作系统的角度看,线程有三种实现模型:
用户级线程 内核级线程 组合模型
用户级线程的创建管理都是由线程库的代码实现完成的,内核并不知情,所以用户级线程的创建代价比较小,不需要内核支持。内核级的线程得创建管理都由
内核完成,创建内核级线程需要操作系统本身的支持,创建的开销比较大,需要进入内核后才能完成。
对于学习线程必须要处理的几个问题:
【1】在单个处理器的系统上,用户级线程和内核级运行时,有什么区别?
在单处理器的内核上,用户级线程的优先级要高于内核级线程,因为但处理器的内核不能支持内核级线程的并行,也会阻塞在单个线程的系统调用上。而且内核级线程还需要由内核创建,无法自己控制;起来线程在用户态的运行,而线程的调度和管理在内核实现,在控制权从一个线程传送到另一个线程需要用户态到内核态再到用户态的模式切换,比较占用系统资源。
【2】在对称多处理器的系统上,两者的运行有什么差别?
在多处理器上,用户级线程当执行到系统调用时会阻塞,一个线程结束完系统调用后才能执行下一个线程,而多核的处理器上,可以同时处理多个线程,具体大小由cpu个数决定
在用户级线程上,CPU是按进程调度的,由用户来确定线程的轮询;内核上是以线程为调度单位的;
【3】同步线程的方法:信号量,互斥锁,条件变量;
对线程实现同步就是实现对临界资源的控制,防止多线程同时访问同一变量;
使用线程安全的函数 | 可重入的函数;非线程安全的函数:一般是使用了全局变量或者静态变量;strtok strtok_r(使用了静态变量)
【4】在多线程下 fork()会怎么运行?
fork()复制的子进程只有一条执行路径,就是fork()所在的那一条执行路径;比如说:父进程有三个线程,其中一个线程fork();那么他的子进程只有一个线程;
fork()都会复制那些内容? 锁 =》 复制 子进程锁的初始状态和父进程相同
线程共享:代码段,父进程打开的文件描述符,data段(写时拷贝) -lpthread 线程库,编译时勿忘;
查看线程id: top -H 显示多个线程使用的id (j f)显示在哪个处理器上 , ps -eLf “L”:显示线程的信息 。 top 查看进程
【5】关于内核中使用的“自旋锁”,有什么特点?
忙等待的锁:一直占用cpu去请求(对临界资源访问时间特别短的时候使用);
非忙等待的锁:变为阻塞状态,不占用cpu;
自旋锁是忙等待的锁:在内核中用来同步的锁;一直不停的测试cpu(因为内核的访问时间特别短)
【6】关于无锁方式和使用普通互斥锁的方式进行同步时,哪种情况下无锁的方式效率更高一些?哪种情况下普通互斥锁的效率更高一些?既然有了互斥锁,那么为什么还要引入无锁的方式同步?引入它重点是要解决什么情况下的问题?
【7】如何创建进程
创建线程的接口:pthread_create()
退出线程:pthread_exit()
合并线程:pthread_join()
互斥锁:pthread_mutex_init() , pthread_mutex_lock() , pthread_mutex_unlock()
信号量:sem_init() , sem_wait() , sem_post()