进程和线程
来源:良许Linux
进程 (Process) 与线程 (Thread) 都是计算机操作系统中的基本概念,在进程和线程之上有程序。
In Computing, a process is the instance of a computer program that is being executed by one or many threads.
程序是静态的,而进程是动态的,程序是作为进程运行的载体,进程会在某一时刻消亡。
程序可以包含多个进程,多个进程并发执行,相互独立,因此,进程也是系统进行资源分配和调度的基本单位。
进程和线程是包含关系,一个进程中至少有一个线程,或者多个线程,一个线程只能属于一个进程。
进程中的所有线程共享该进程的所有资源,比如内存空间,每个线程都可以使用这个内存空间。
Mutual exclusion (互斥锁)
有时候某些资源只能同一时间被一个线程使用,这个时候就要用到互斥锁。
Semaphor (信号量)
有时候进程中的某些资源只能被指定数目的线程同时使用,比如资源A的信号量为N,表示同时最多能有N个线程使用A,其他线程必须等某个线程使用完A释放出新的名额才能使用A。
为什么需要多线程呢?
每个进程都有自己独有的代码和数据空间(程序的上下文),进程的切换消耗要大于线程的切换消耗。线程可以看作是轻量级的进程,每个线程也有自己的「运行栈」,「程序计数器(PC)」和「线程的本地存储」,所以有时候用多线程代替多进程会节省很多开销。
进程线程的状态:
进程包含五个状态:
初始态,执行态,等待状态,就绪状态和终止状态。
线程也包含五个状态:
新建(New)、可运行(Runnable)、运行(Running)、阻塞(Blocked)、死亡(Dead)。
进程以及线程之间的交互:
进程之间的通信包括:管道,系统IPC (包括消息队列、信号量、共享存储),SOCKET。
管道有三种方式:
- 「普通管道」PIPE
- 「流管道」s_pipe
- 「命名管道」name_pipe
线程之间的通信在JMM(Jave Memory Model)中是通过共享内存来实现的。为了保证多线程之间的数据的一致性,可以使用锁机制,实现线程之间的操作的同步、有序,例如「synchronized锁、Lock锁、Atomic原子类」。
并发 (Concurrency)
来源:知乎@大宽宽
Concurrency is not Parallelism.
并发其实是一种抽象概念,「并发」和「并行」不是一回事。「并发」说的是**处理(Deal)的方法,而「并行」说的是执行(Execution)**的方法。
Concurrency enables parallelism & makes parallelism easy.
制定一个并发的方法让并行变为可能,如果一件事根本没有并发的方法,那么无论有多少个人都没法做到并行,比如拧灯泡只能一个人拧,再多的人也只能看着。并行的上限就是由并发决定的,如果程序被设计成最多用到4个CPU并发,那么这个程序放在4个CPU和8个GPU的机器里运行是没有区别的,但是它在4个CPU上运行肯定比在单核CPU上运行要快。
并发本身就没有先后顺序,并发的任务之间不能有依赖关系,即A可以在B之前或者之后或者同时执行,不影响结果。
将大的任务拆解成许许多多小的可以并发的任务是重要的编程思想。
比如要实现一个获取用户信息的程序,首先根据登陆的token获取userId,然后用这个userId来分别去并发地做三个任务:获取用户基本信息、获取用户积分信息、获取用户订单信息,然后将三个结果结合来得到最终的用户信息。
高并发
高并发是指可以让软件系统在一段时间内能够处理大量的请求,高并发说的是最终效果,即只要你能用一个CPU核心完成处理请求的要求,那么也算是高并发。