最近工作中需要用到并发以提高模块性能,之前对这一块的认识太浅薄并且缺少相关实践,以至于跟大神们讨论方案时经常被问住,遂决定利用空闲时间好好看看并发,多线程,高性能服务器这方面的知识,跟同事交流了下,这块的经典书籍还是不少的,《java并发编程实战》据说是公认的经典,就从它开始吧~
btw,关于如果选择书籍,我又想起了那句话:重要的不是选择一个最好的开始,重要的是马上立刻现在就开始。
第一章 简介
1. 最早
一台计算机从头到尾只能运行一个程序
2. 进程出现
后来,计算机系统在处理多个用户/程序的任务时,采用分片的方式进行调度,即以有限时间片单位执行当前任务后切换到另一个任务继续执行,一个任务可以看做一个进程。之所以这么做,主要原因有两个(书中写了好几个):
1. 提高资源利用率。想象下A程序在等io时cpu正空闲着,不给B用岂不是浪费?
2. 公平性。为了使多个用户/程序公平访问计算机资源。
3. 多线程的优势
基于与2相同的原因,多线程出现了,但相比多进程有更大的优势,最明显的就是相比操作系统的调度,线程的切换开销很小,并且可以共享进程内的资源,比如内存句柄,文件句柄等。对于现代多处理器 or 多core的单处理器,如果一个程序只有一个线程,那最多就用到了一个core,无法发挥多处理器的全部功力。
几个多线程的例子:
1. web程序。假设有若干个请求同时发送到服务器,如果后台服务时单线程的,那一个请求的处理就将阻塞后面一堆请求。但如果为每个请求开一个单独的线程(实际应用中不可能,一般是用线程池),将不存在这样的问题
2. GUI程序。想象一个cpu密集型的GUI程序,点击按钮会将斐波那契数列(Fibonacci sequence)的第n个数字打出来(n由用户输入),假设计算过程没有缓存,并且使用的是效率奇低的算法,那GUI将被计算过程阻塞,此时用户将无法继续输入,用户体验会很差。
多线程的需求可以概括为两点:
1. 关注点分离。 不同线程干不同的事情,方便维护,方便测试。
2. 提高性能。 这个不用讲了吧?
4. 多线程的大坑
多线程似乎很完美,可以共享变量,开销低,性能提高爽歪歪,但别高兴的太早,当你使用的多线程是状态无关时,那还真不会有问题,一旦状态相关那就会随时悲剧,造成非期望的结果。ps:这里的“状态相关“可以理解为是否使用了共享变量。
一个简单的例子,假设现在有一个将初始值是0的整数n递增5000次的多线程程序,用到了5个线程,每个线程各将n递增1000次这(这个需求很奇怪?yes,仅仅是个例子),好的,现在来写代码,每个线程的c代码可能是这样:
void inc(int *n)
{
++*n;
}
你期望得到的结果是5000, 结果你跑10次出来的结果可能有好几个都不是5000(比5000小),原因在哪里?ok,原因在于这里的n是共享变量,但++*n并不是原子操作,它需要先对n执行自增操作再赋值给自身,考虑线程A对n自增成功的一刹那另一个线程B对其自增并赋值成功,此时A线程再赋值,等于B的自增操作丢失了,这显然不是你期望的结果。
第一章的内容就这么多,很简单,都是学生时代就已经掌握的东东,不过还是把它写了出来,大厦都是根基慢慢打出来的, 下一章见。