单核处理器也支持多线程代码,CPU通过给每个线程分配CPU时间片来实现.
CPU通过时间片分配算法来循环执行业务,任务执行一个时间片后会切换到下一个任务.任务从保存到加载的过程就是一次上下文切换.
上下文切换会影响多线程的执行速度.
并发操作不一定快,创建线程及上下文切换有固有的开销.
测试切换次数及时长
使用 LMbench3 测量上下文切换时长
使用vmstat
测量上下文切换次数
1 | vmstat 1 |
CS(Content Switch)表示上下文切换的次数
如何减少上下文切换次数
- 无锁并发编程.多线程竞争锁时,会引起上下文切换,所以处理数据时,可以通过避免使用锁减少上下文切换(例:数据Hash取模分段,不同线程处理不同的数据).
- CAS算法.(例:Atomic包使用了CAS算法来更新数据,不需要加锁)
- 使用最少线程.避免创建不需要的线程,线程数创建过多会导致大量线程处于等待状态.
- 协程:在单线程里实现多任务调度,并在单线程里维持多个任务间的切换
实际操作
用jstack命令dump线程信息
1 | jstack 203 > /home/w/www/dump |
统计线程状态分布
1 | grep "java.lang.Thread.State" dump1 | sort | uniq -c |
查看 WAITING (on object monitor)状态的线程的具体情况,例如线程闲置,需要调小线程池容量
文章链接 https://fangzongzhou.github.io/2020/09/25/计算机/技术栈/Java/并发编程/上下文切换/