如何减少上下文切换
- 无锁并发编程: 多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash算法取模分段,不同的线程处理不同段的数据。
- CAS算法:Java的Atomic包使用CAS算法来更新数据,而不需要加锁。
- 使用最少线程
- 使用协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。
避免死锁的常见方法
- 避免一个线程同时获取多个锁
- 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源
- 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
- 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况
找出问题所在
在并发编程中,将代码执行速度加快的原则是将代码中串行执行的部分变成并发执行, 但是如果将某段串行的代码并发执行,因为受限于资源,仍然在串行执行,这时候程序不仅不 会加快执行,反而会更慢,因为增加了上下文切换和资源调度的时间。例如,之前看到一段程 序使用多线程在办公网并发地下载和处理数据时,导致CPU利用率达到100%,几个小时都不 能运行完成任务,后来修改成单线程,一个小时就执行完成了。
资源限制 是指在进行并发编程时,程序的执行速度受限于计算机硬件资源或软件资源。硬件资源限 制有带宽的上传/下载速度、硬盘读写速度和CPU的处理速度。软件资源限制有数据库的连接 数和socket连接数等。
命令
使用jstack命令dump线程信息,查看pid进程里的线程
1
jstack pid > stack.txt
统计所有线程分别处于什么状态
1
grep java.lang.Thread.State stack.txt | awk '{print $2$3$4$5}' | sort | uniq -c