操作系统学习之进程线程
定义:
进程:cpu分配资源的最小单位
线程:程序运行的最小单位
为什么需要进程和线程:
一个进程对应一个打开的应用程序,操作系统可以同时运行多个应用程序,但是要保证 每个应用程序都是独立的单元,进程本质上是一个独立的内存空间 执行环境加上下文
在应用程序内部 经常会遇到阻塞的情况,这个时候给用户的体验就不好,加入多线程,使得耗时任务可以放到后台线程里面做
多进程 多线程管理:
竞争问题:多个进程或线程访问共享资源下导致的竞争问题。
临界区:代码中 关于访问共享资源部分的代码
原因:cpu会在多个进程之间切换,如果A进程访问了某个共享资源,正在修改中,突然被切到另外一个进程,如果这个进程也修改了这个共享资源,这就会导致冲突
解决:
peterson算法: 缺点:需要忙等待
在考虑peterson算法的时候,必须加入时间的考虑,peterson算法的核心在于这句话:
while( share == threadId && own[other] == TURE )
这句话的意思是说,如果本函数是运行在本进程内部,而且其他的进程还在临界区,就一直while。
信号量:假设存在两个共享资源,和3个并发线程,那么 我们必须想到一种办法 使得可以允许两个线程并发,如果超过2个 就等待,这就是信号量的作用,
信号量机制:假设信号量是2,那么首先进来一个线程,信号量-1,然后再进来一个线程,信号量-1,此时 信号量是0,当再进来一个线程的时候,这个线程必须等待,直到有一个线程出去,并把信号量+1,这个时候 之前等待的那个线程就可以进去了。
互斥锁:互斥锁的作用是对临界区加以保护,以使任意时刻只有一个线程能够执行临界区的代码。实现了多线程之间的互斥
互斥锁的实现:
借助于硬件级别的原子操作
互斥锁导致的问题:
死锁:
假设A线程持有锁a,B线程持有锁b,而线程访问临界区的条件时同时具有锁a和锁b,现在A线程处于休眠状态,他等待B线程离开锁b,然后将自己唤醒吗,同样 B线程也处于休眠状态,他等待A线程离开锁a将自己唤醒。
自旋锁:B线程看到A线程使用了锁之后,B线程是将自己挂起还是一直等待A线程释放锁?如果挂起的话 将消耗线程切换的性能,如果一直等到的话,需要不断的询问锁是否开了,消耗cpu性能,自旋锁 就是这种 通过不断询问锁是否开的一种操作。
条件锁
读写锁
http://www.cocoachina.com/articles/22402
管程
https://blog.csdn.net/chthq/article/details/7881117
c# 多线程编程
开启多个线程可以充分利用cpu, 将阻塞式运算放到其他线程 使得主线程一直相应用户是常见的设计,因为多线程的存在,使得线程之间的管理变得复杂,常见的问题有:
资源竞争:一个资源在一个时刻应该只允许一个线程操作,否则会造成混乱
资源互斥:通过互斥,实现避免资源竞争
条件管理:有的线程具有先后顺序,或者说必须满足某个条件才会执行
读写问题:读可以多个线程,但是写只允许一个线程
因为上述种种问题,衍生出:信号量,互斥锁,条件锁。读写锁等多种用于协调管理线程的锁工具。
因为锁的管理特别麻烦,有时候 会产生死锁的问题,于是 出现了管程 一种易于书写的方式