一、背景

1、为什么需要多线程

多线程出现的原因大致有俩点:

  • 相对于内存、IO、网络请求等,CPU的速度太快,这样就导致CPU的利用率不高;多线程可以有效地提高CPU的利用率;
  • 多核CPU的发展;现代计算机都是多核心的CPU,如果应用只是单线程的话,那其他核心就白白浪费了;

可以总结出:多线程的出现就是为了解决CPU利用率不高的问题。

我是一个CPU:这个世界慢!死!了!

2、多线程的缺点

多线程的出现解决了CPU利用率低的问题,也可以理解成CPU可以同时做很多东西,大大的提高的工作效率。

但多线程也有缺点:

  • 慢:奇怪了把?多线程是为了提高执行效率,怎么这里就慢了?这里是指CPU切换上下文花费的时间。

    当一个CPU在一个线程执行的时候,准备跳到另一个线程去执行代码。这时候,它需要先将在这个线程做的工作内容存储起来;然后跳到另一个线程,再去读另一个线程之前做的内容;最后再去执行真正工作代码。我们把CPU保存工作内容和读取工作内容的这段工作称为切换上下文。

    CPU执行一个切换上下文大概花费0.3ns ~ 1us,而一个时钟周期才0.38ns

  • 占用资源多:每个线程都会有独立的方法栈。而在大型项目中方法栈存储的东西还是挺多的,如果有非常多的线程,那加起来所占的内存还是挺“可观”。

上面是多线程的缺点,多线程真正在应用到实际开发中,也会带来很多问题:

  • 线程安全问题:共享变量、死锁等
  • java中多线程的难理解、难使用

3、多线程缺点的解决方案 -- 协程

我们知道多线程缺点来源于CPU在多个线程之间切换所花费的太多时间,那如果只让CPU只运行一个线程,让这个线程再去调度其他线程。这样,CPU就不会有切换上下文所花费的时间了。这也是协程的原理。

不过java本身是不支持协程的。所以如果想要实现协程的功能,还需要自己写线程调度器。或者从网上找找其他写好的。

协程的优点:

  • 占用资源少;由于占用资源少,它可以达到更高的并发度;
  • 更快;因为它始终有个线程占用CPU

协程解决的是:多线程之间调度慢、占用资源多的问题。但它没有解决多线程所带来的线程安全问题。

二、线程底层模型

1、Thread类的每一个实例代表一个JVM中的线程

  • 在Linux上称为轻量级进程,和进程无本质区别
  • 在windows上使用系统线程

进程中的线程会有一个共享内存空间。而进程与进程之间是不存在共享内存。

(1)优点

  • 简单,直接依赖操作系统的调度器

(2)缺点

  • 占用资源多
  • 上下文切换慢
  • 不灵活,无法实现灵活的优先级

2、用户态和内核态

因为操作系统的资源是有限的,如果访问资源的操作过多,必然会消耗过多的资源,而且如果不对这些操作加以区分,很可能造成资源访问的冲突。所以,为了减少有限资源的访问和使用冲突,Unix/Linux 的设计哲学之一就是:对不同的操作赋予不同的执行等级(有多大能力做多大的事),用户态(User Mode)和内核态(Kernel Mode)。

results matching ""

    No results matching ""