前言:
在并发编程学习中,我们知道并不是更多的线程就能让程序最大限度地并发执行。因为这其中涉及到线程间的上下文切换。而其中减少上下文切换的手段有 无锁并发编程、CAS算法、使用少的线程、协程等手段。
那么为什么说无锁并发、CAS能减少上下文切换呢?
本文导读
- 什么是线程间的上下文切换?
- CAS会没有线程上下文切换这话对吗?
- 既然是多线程开发,必然会涉及到上下文切换。那为什么无锁并发编程能减少上下文切换?
正文
什么是上下文切换
上下文切换简单理解
CPU通过时间片算法来循环执行任务,当前任务执行一个时间后悔切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次,切换回到这个任务时,可以在加载这个任务的状态。所以任务保存到加载的过程就是上下文切换。
这里我们记住一个概念:CPU时间片。时间片是CPU分配各个线程的时间。时间片的实际很短,所以在单核处理器中就感觉也是多线程并行执行。
为什么无锁并发编程能减少上下文切换?
首先得明确 无锁并发和CAS并不是说避免了上下文切换,而是减少了上下文切换!
因为并发编程肯定就是会涉及到线程的切换的。
那么为什么可以减少呢?
在讨论这个问题,我们得明确触发线程的添加有哪些:(下面讨论是基于线程数>CPU核数)
1、线程运行的时间片时间用完了,线程切换。
2、若线程在时间片结束前阻塞或结束,线程切换。
明确了上面两点,我们再看有锁并发和无锁并发,在不考虑IO等因素下,有锁并发在没有竞争到锁的情况下会进行阻塞,造成了线程提前进行线程切换。无锁并发则只有时间片用完后才进行线程切换。
那么我们再看看CAS算法,当线程进行CAS算法更新的时候,如果发现不是期望的数据,那么他会进入循环进行更新,或者时间片用完后切换线程。而在本次时间片内,存在本线程多次CAS更新后更新成功,从而减少了线程的切换。
补充
上文提出线程阻塞会引起线程切换,而锁只是引起阻塞的其中之一。此外还有IO操作、数据库连接数等因素。因此在并发编程中,要将上下文切换的实际考虑进去。
例如:单核CPU中,是并行处理还是串行处理速度快?
在不考虑资源限制的挑战时,肯定是单线程处理快了,因为没有上下文的切换。
但是,如果考虑存在I/O阻塞的问题,线程在执行过程中需要等待。比如我们要获取10个网络资源,每个网络资源需要5s。如果使用单线程的话,总共需要50s才能完成任务,而如果使用多线程的话,我们开启10个线程,忽略线程开启的时间,完成任务总共需要5s。因此对于IO密集型任务,适合采用多线程。