1.并发带来的问题
并发编程的目的是为了让程序运行的更快的,但是,是不是启动更多的线程就能让程序最大幅度地并发执行?这个问题值得我们深思。
而我们一旦通过多线程去使得程序运行的更快,那么就会遇到几个问题:
- 上下文切换
- 死锁
- 硬件和软件的资源限制
那么当我们出现这些问题的时候,该如何去解决或者是避免呢?
1.1.上下文切换
1.1.1.解释上下文切换并说明其问题
首先,想一个问题,为什么当我们使用多个线程并发执行的时候,为什么感觉到像是同时执行呢?
通过我们学习的操作系统的知识来看,当进程从就绪到执行状态,是需要系统分配时间片来执行的,一旦时间片结束或者任务执行完毕,就会回到就绪状态。(注:时间片是cpu分配给执行单元的时间)
而线程同样如此,cpu通过给每个线程分配cpu时间片来实现线程并发执行,而cpu分配给每个线程的时间非常短,所以cpu需要通过不停地切换线程执行。因此,让我们感觉到线程是同时执行的,时间片一般是几十毫秒。
下面这两幅图,可以很形象的展示并行与并发的区别。
并行
并发
而我们可以再想想,当我们从一个线程切换到另一个线程,然后在回来,是如何回到之前的状态呢?
事实上,当切换到另一个线程的时候,切换前会保存上一个任务的状态,以便下次切换回到这个任务时,可以再加载这个任务的状态。
这个任务从保存再加载的过程其实就是一次上下文切换。
从实际生活中,我们也很容易感受的这件事情。当我们看书的时候,由于要去做其他事情,我们先会将看到的页面折起来,记录这个状态,然后事情结束后继续看书的时候,从折角处继续观看。但是这个过程,是很影响看书效率的,我们要回忆起之前的内容,然后继续观看。这事实上,就是上下文切换带来的影响。
1.1.2.并发执行一定比串行快吗?
我们觉得,当多件事情并发的去执行和串行比较,按照生活经验考虑,是并发的比较快,但是事实是这样吗?我们不妨做一个测试。
private static final long count = 10001;
public static void main(String[] args) throws InterruptedException {
concurreney();
serial();
}
private static void concurreney() throws InterruptedException {
long start = System.currentTimeMillis();
Thread thread = new Thread(new Runnable(