第一章 并发编程挑战


一个任务从保存到再加载的过程就是一次上下文切换


如何减少上下文的切换

  • 无锁并发编程。多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash算法取模分段,不同的线程处理不同段的数据。
  • CAS算法。Java的Atomic包使用CAS算法来跟新数据,而不需要加锁。
  • 使用最少线程。避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态。
  • 协程。在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。

减少上下文切换实践

思路 通过减少线上大量的WAITING的线程,来减少上下文切换次数

  • jstack命令dump线程信息,看看pid为xxx的进程里线程都在做什么。
  • 统计所有线程分别处于什么状态
    grep java.lang.Thread.State dumpxxx | awk '{print $2$3$4$5}' | sort | uniq -c
  • 打开dump 文件查看处于WAITING 的线程在做什么
  • 比如线程池里的线程接收到的任务少,大量线程闲置,我们可以找到配置文件修改配置信息,然后重启任务查看

死锁

在一些复杂的场景中,可能会遇到,A线程拿到锁之后,因为一些异常情况,没有释放锁(死循环),或者是A线程拿到一个数据库锁,但是释放锁的时候抛出了异常,没有释放掉。导致B线程获取不到锁。
我们只能通过dump线程查看到底哪个线程出现了问题,然后我们找见对应代码去避免

  • 避免一个线程同时获取多个锁
  • 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
  • 尝试使用定时锁,使用lock.tryLock来替代使用内部锁机制
  • 对于数据库,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

你可能感兴趣的:(第一章 并发编程挑战)