1、并发编程的艺术之基础概念

176 阅读4分钟

1. 上下文切换

1.1 什么是上下文切换

即使是单核处理器也会存在多线程执行的任务(比如电脑浏览网站的同时可以听歌)。不同线程的执行是通过CPU为每个线程分配CPU时间片来实现的。CPU时间片的分配是通过时间片分配算法来实现的,因为时间片非常短,一般只有几十毫秒,所以CPU需要一直不停的轮询切换,达到感官上任务多线程的表象。 当前任务执行完一个时间片后,时间片会被切换,分配给其他的线程。但是在时间片切换前会保留当前任务的状态,以便下次时间片切回来时,可以再加载到任务的状态。 任务从保存到再加载的过程,就是上下文切换。线程的上下文切换,会影响线程的执行速度。

1.2 多线程一定快吗?

线程执行并发的数目不高时,多线程不一定快。因为线程的创建和上下文切换同样需要消耗时间资源。

1.3 如果减少上下文切换?

多线程中上下文切换会消耗大量的时间资源,所以减少上下文切换就可以减少多线程执行过程中时间资源的消耗。 减少上下文切换常用的方法:无锁并发编程、CSA算法、使用最少线程、使用协程。 无所并发编程:多线程竞争锁时,会引起上下文的切换,避免使用锁,可以采取其他方法,比如将数据id按照HASH取模,不同的线程处理不同区间的数据。 CAS算法:compare and swap,比较交换算法,Automic中使用CAS算法来更新数据,而不用创建锁 使用最少线程:任务少时,不需要创建过多线程,线程过多会导致许多线程处于等待状态。 使用协程:在单线程中实现多任务的调度,并且在单线程中维持多个任务的切换。

2. 死锁

2.1 什么是死锁

线程的持续的等待其他线程释放锁的过程,叫做死锁。死锁对业务而言是可感知的。因为死锁后程序将无法进行下午

2.2 避免死锁的几种方式

● 避免一个线程同时获取多个锁 ● 避免一个线程同时占用多个资源,尽量保证一个线程只占用1个资源 ● 使用定时锁,代替使用内部锁机制 ● 数据库的锁,加锁和解锁必须在一个数据库连接里,避免加锁解锁失败

3. 资源限制的挑战

3.1 什么是资源限制?

资源限制是指在程序的执行过程中,程序的执行速度受限于硬件资源和软件资源。 例如,服务器的带宽只有2M/s,某资源的下载速度是1M/s,同时下载10个资源,但是受到带宽影响,下载速度并不会变为10M/s。 硬件资源考虑带宽,磁盘读写速度和CPU处理速度。软件资源考虑数据库连接数和socket连接数

3.2 资源限制引发的问题

并发加载代码速度的原则就是将串行执行的任务改为并行执行。但是有时候把串行执行的代码改为并行执行,受资源限制,代码执行反而会更慢,因为增加了上下文切换和资源调度时间。

3.3 如何解决资源限制引发的问题

硬件资源受限,可以考虑采用服务器集群,不同的机器处理不同的任务。 软件资源受限,可以考虑重复利用资源池。比如使用连接池将数据库和socket链接复用,或者在调用对方WebService时,只创建一个链接

总结

  • 线程越多不一定越快,因为线程的上下文切换也会影响线程执行效率
  • 线程持续等待其他线程释放锁的过程叫做死锁
  • 资源限制是指程序的执行速度受限于硬件资源和软件资源