操作系统
789字约3分钟
2024-09-26
提问
- 进程, 线程和协程的区别?
- python能真正地做到并发吗? 为什么?
- Go的协程是如何调度的?
- 乐观锁和悲观锁了解吗?
进程, 线程和协程的区别?
进程和线程
进程是资源分配的基本单位, 每个进程都有自己独立的地址空间, 线程是依附于进程存在的,没有独立地址空间.线程是最小的执行单位. 从并发性来说, 线程的并发会好一些.(先别说后面的)并发性好是因为线程的切换无需切换页表, 进程需要切换页表, 会导致TLB的命中下降. 物理地址和虚拟地址的转换效率变低. 线程的安全性低. 因为线程的崩溃会导致这个进程中所有线程全部崩溃, 但是进程的崩溃不会影响其他进程 线程通信简单. 可以在堆上进行通讯, 进程通信需要用到管道, 消息队列, 共享内存.
同一个进程中的各个线程可以共享该进程的所有资源.包括: 虚地址, 已打开文件, 定时器, 信号量等. 但是不能共享进程中某线程的栈指针.
线程和协程
协程是一个用户态的线程. 线程的CPU信息在内核栈中, 线程的切换需要在内核态中完成. 协程的切换在用户态, 调度由用户完成.
协程和goroutine
goroutine有一个GMP的调度.
python能真正地做到并发吗? 为什么?
python无法做到真正的并发. 因为它是个脚本语言, 运行过程中编译, 存在GIL全局锁的问题.
但是python仍然存在Thread
语法是因为有些任务并非CPU密集的, 对于IO密集的任务可以使用多线程编程.
Go的协程是如何调度的?
G: goroutine P: 资源 M: machine 执行的物理机器
P和M进行绑定后从本地local的队列中获取G, 如果本地队列为空则会从global队列中获取或者抢夺其他的local队列.
详情请查看Go语言中的并发
乐观锁和悲观锁
乐观锁和悲观锁是为了解决并发场景下, 多个线程对同一个变量的操作带来的数据一致性问题.
乐观锁
对并发采取乐观的态度, 并不真正加锁. 只在修改数据前检查数据距离自己上一次读取是否被修改过了, 如果没有修改过则进行修改, 如果修改过了则不修改.
判断是否修改过的方法主要有: 版本号和CAS(compoare and swap)等机制.
悲观锁
对并发采取悲观的态度, 在修改数据前先尝试获取锁, 未获取到之前阻塞. 在操作完成后释放锁.