[译] 多线程科普(一)
由于硬件和智能操作系统支持,现代CPU都能够在同一时间执行多个操作,这种特性让你的程序运行更快,执行速度和响应速度都能大幅提升。
如果有效利用这种特点(多线程和多线程),那么编写出来的代码将非常有趣,但同时也非常有挑战,因为它需要你了解计算机内部是如何运作的。
1:线程
现代操作系统在同一时间能运行多个程序,这就是为什么你一边使用浏览器(软件)上网,又能同时用音乐播放器(另一个软件)听歌,每个程序当它运行的时候就是一个进程,操作系统本身有很多技巧让一个进程和其他进程一起运行,它也能充分利用底层硬件的特性(比如多核),反正不管怎么样,最终给你的感觉就是程序在同时运行。
同一时间运行多个进程并不是同时运行多个操作的唯一方法,每个进程有能力运行多个子任务,这就是线程,你可以认为一个线程就是进程的一个分片。
每个进程至少有一个线程,称之为主线程,根据程序/程序员都需要,其它线程能够启动或中止,多线程讨论的就是一个进程运行多个线程的故事。
举个例子,一个音乐播放器它的界面就是主线程,实际播放音乐的引擎就是子线程。
你可以认为操作系统就是装满了众多进程的一个容器,而每个进程又是多线程的容器,当然这篇文章主要说的是多线程。
2:进程和线程的区别
操作系统会为每个进程分配独立的内存空间,默认情况下某个进程的内存空间无法被其他进程访问,比如浏览器就不能操作音乐播放器的内存空间;即使相同程序的两个进程也不能访问对方的内存空间,比如你开启了两个浏览器窗口。如果想让不同进程之间共享数据,可以采用IPC技术。
和多进程不一样的是,操作系统可以让子线程共享主进程的内存空间,比如音乐播放器中的界面窗口很容易被播放引擎控制,反之亦然。
也就是说子线程之间通信非常方便,重要的是线程比进程更轻量:资源占用更少,启动更快,所以大家也称线程就是轻量级的进程。
使用多线程很容易在同一时间执行多个操作,如果没有多线程,你需要为每个任务写一个程序,然后以多进程的方式运行,并让操作系统进行调度,这种编写方式很困难(IPC通信很麻烦),也很耗费资源。
3:Green threads
到目前为止,前面提到的线程都是由操作系统管理的,进程想要触发一个线程必须要告诉操作系统,由操作系统最终创建,但并不是所有平台都支持多线程。
那怎么办?平台如果不支持多线程,可以采用Green threads模拟技术,能够在一个进程中模拟出多个线程。
举个例子,如果底层操作系统不支持多线程,那么VM虚拟机就可以使用Green threads技术。
Green threads创建、管理线程非常快,因为它绕过了操作系统,但也有缺点(本文不描述)。
green threads这个词来源于Sun Microsystem的Green团队,他们在90年代创造了Java线程库,现在Java已经不在使用green threads技术,在2000年转而使用操作系统原生支持的线程库了。其他一些语言,比如Go还在使用green threads技术代替原生多线程技术。
4:使用线程做什么?
为什么进程应该使用多线程?就像我前面提到的,并行(parallel)处理能够加速运行,比如一个编辑器处理一个视频,编辑器足够聪明,可以跨多个线程执行渲染操作,每个线程处理视频的一部分,假如说一个线程处理一个视频要30分钟,两个线程就是15分钟,以此类推。
可真的这么简单吗?有是那个重要的点需要记住:
(1)不是每个程序需要多线程,如果你的程序都是顺序操作,或者要等待用户中断处理,多线程可能就没什么用了。
(2)不是说分配多个线程就能让程序运行更快,每个子任务并行操作的时候都必须思考和仔细设计。
(3)不能100%保证线程在同一时间并行操作,这取决于底层硬件或语言(比如Python的GIL)。
接下去这一段话很重要,如果你的电脑不能在同一时间执行多个操作,操作系统将伪造(后面会说)。
现在你要注意的是,并发(concurrency)让你感知在同一时间运行多个任务,而真正的并行(parallel)才是真正在同一时间运行多个任务(这需要操作系统多核处理)。
今天先说到这儿,近几天就会更新后半部分!