操作系统线程互斥,锁死机制的简单介绍

操作系统线程互斥,锁死机制的简单介绍_第1张图片

用户线程的切换,是内核决定,由调度器分配时间片调度到内核空间,转换成内核线程,然后指令重排序交给CPU.CPU没有执行过程中的中断时间,是不断的在运行,只是调度器提前将线程调度好,将多个线程的指令排好交给CPU。那么这种混合插入就是我们上层理解的线程调度。对CPU而言,所有的线程都是 串行的。

对于一个多线程并发的多次处理或者重复处理一个任务,如果这个任务就是原子操作,(如读、写操作,先是寻址,然后读出数据,再然后寻址找到要写回来的地址将数据写进来;也有可能是指针操作,先是寻址,读出改地址里存储的地址数据,然后寻址跳转,找到指向的地址,将数据读出来,然后再寻址,将数据写进去。那么这一长串的操作就是原子操作,中间不可能有调度器在调度指令的时候,将这些指令分割开来处理。)对于单个CPU系统而言,那么没有必要同步或者互斥同步。互斥就是单个CPU最基本的特性,只要有一个线程在执行,那么其他的互斥线程都在停止状态。调度器会记录有互斥的线程,在调度的时候不会去调度。对于原子操作不可能有调度器的中断,这是硬件指令集决定的,所以是硬件决定的。硬件会在原子操作上,分配一定时长的操作时间。而调度器分配的时间片就是基于这个操作时间的,是操作时间的整数倍。


对于单个CPU系统,两个线程互斥,但是又存在竞争,比如说一个线程resume,但是又调度了terminated;那么这个线程被调度器调回来,又调回去,换句话说就是两个线程被调度器切换来又立即切换回去。那么这两个线程出现了死锁。死锁、互斥、同步是两个线程之间的概念。怎么减少死锁的风险,很明显是在线程调度处理上我们加上一些机制。比如对于某一线程正在被CPU执行一段代码,这段代码加有锁(只允许单个线程执行完毕之后,才能有下一下线程执行),但是时间片结束,调度器又调了另外的线程,但是这个线程也是执行这段代码,那么两个线程出现了,互斥区域中的竞争,那么内核要将这个线程直接从对应的内核空间剔除到用户内存空间,再次由系统依据调度算法调到内核空间。这就是阻塞。说白了,就是线程被调度了,但是不能执行当前的代码指令,只能被调度器剔除挂起,那么这个线程在一轮的调度中没有任何的执行,相当于阻塞中。
阻塞,内核将线程剔除到用户空间,这样很耗费资源,因为系统内核是不能被用户空间访问的;因为内核是完全保护起来的,这也是系统稳定很重要的因素。但是内核空间可以访问用户空间,通知线程被调度到内核区。那么线程从用户区进去到内核区,那么必然有存储空间在内核区重新建立,数据重新读取到内核中。相反,从内核中将线程剔除,依然有数据从内核区读到用户存储区。为了优化或者减少线程的阻塞,首先可以判断线程将要执行的代码是不是有锁,而且和已执行或者执行过的线程存在锁互斥。如果存在就不被调度,等待下一次调度。或者在调度的时候没有锁机制的判断,如果被调度的线程存在所互斥,那么暂停被调度,直接将分配的时间片转移到下一个要调度的线程。也可以
在调度处理的时候发现要执行的代码是含有锁互斥的代码,那么转移到没有锁存在的代码先执行。总之减少线程什么也没有做,便从内核剔除到用户空间。


那么为什么操作系统发现,互斥的线程,将其剔除到用户空间呢,重新排队进入到内核空间,然后逐步分配时间片等待调度呢?这个是出于安全考虑,或者系统内核的设计。系统内核设计上,在内核中的线程都会安排到时间片,也就是都会被调度器调度。没有等待的概念,等待的概念只在用户空间。在用户空间等待排队,那么在内核中就没有对应的执行的内核线程(将用户空间的线程指令copy到内核空间去执行)。所以这也是为什么将互斥的线程调到用户空间排队,是防止再被调度到。


那么为什么操作系统分为用户空间和内核空间呢?你可以想象,用户在操作的时候很可能随时删除一个线程(关闭),和创建(打开)一个新的线程,用户这些操作如果直接映射对应到内核上,会导致调度器自我调整的时间很少,内核还要抛出一部分资源来监听和相应用户操作(这也就是将现在的操作系统将用户空间和内核合并在一起而且也可以通信)。那么系统可能不稳定,综合设计经验,操作系统将只顾和CPU打交道的部分封装为内核,相应用户的部分封装为用户区。


对于多核处理器系统,那么线程的并发可以是多个CPU同时处理,也可以多个线程在切换时间片中处理,那么考虑线程的死锁和同步,互斥就要考虑其他cpu是不是会处理。

同步处理的数据如何同步,保证数据的统一性。


你可能感兴趣的:(操作系统线程互斥,锁死机制的简单介绍)