并发编程笔记1

上下文切换

单核处理器是如何支持多线程编程的? CPU通过给每个线程分配CPU时间片来实现。

  • 时间片是CPU分配给各个线程的时间,时间片非常短,CPU通过不停切换线程执行,切换时间很快,让人感觉是在同时执行。
  • CPU通过时间片算法来循环执行任务,当前任务执行完一个时间片后会切换到下一个任务,切换前辉保存上一个任务的状态,便于下次切回的时候可以再加载这个任务的状态。任务从保存到再加载的过程就是一次上下文切换。
  • 因为线程有创建和上下文的切换的开销,并发执行累加操作次数没有很高的时候,速度会比串行执行慢。

测试上下文切换次数和时长的工具

  • 使用Lmbench3可以测量上下文切换的时长
  • 使用vmstat可以测量上下文切换的次数

如何减少上下文切换

  • 无锁并发编程。多线程竞争锁时,会引起上下文切换,可以用些方法来避免用锁。比如对数据id计算取模分段,不同线程处理不同段的数据。
  • CAS算法。CAS:Compare and Swap, 翻译成比较并交换。 java.util.concurrent包中借助CAS实现了区别于synchronouse同步锁的一种乐观锁。
  • 使用最少线程。避免创建不需要的线程。比如任务很少,不比创建大量线程,可能会导致大量线程处于等待状态。
  • 协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。具体java如何实现协程要找个时间研究下。

死锁

dump分析死锁

  • 一旦出现死锁,业务是可感知的,不能继续提供服务。只能通过dump线程查看是哪个线程出现了问题。
  • Jstack是JDK自带的命令行工具,主要用于线程Dump分析
  1. 我们先用Jps来查看java进程id(或者Linux的ps命令)


    并发编程笔记1_第1张图片
    image.png
  2. jstack的使用


    并发编程笔记1_第2张图片
    image
  3. jstack输出线程dump信息到文件


    image
  4. 查看文件,关键字是at DeadThread.run,比如at DeadThread.run(DeadThread.java:37),说明Thread-1实在DeadThread类的37行处发生死锁


    并发编程笔记1_第3张图片
    image.png

避免死锁的常见方法

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

你可能感兴趣的:(并发编程笔记1)