java并发编程的艺术读书笔记(一)

并发编程的目的是为了程序运行的更快。java

1.上下文切换:算法

时间片:cpu分配给各个线程的时间。数据库

单核处理器也支持多线程执行代码。编程

cpu经过时间片分配算法来循环执行任务,任务从保存到再加载的过程就是一次上下文切换。多线程

多线程不必定快,由于线程有建立和上下文切换的开销。并发

使用Lmbench能够测试上下文切换的时长(何时须要看这个参数呢)。socket

使用vmstat能够测量上下文切换的次数。好比:执行vmstat 1,再看cs的值,cs表示上下文切换的次数,这个值表示每一秒钟上下文切换的次数。(何时须要用到这个命令呢?)测试

减小上下文切换的方法:优化

1.无锁并发编程。多线程竞争锁时,会引起上下文切换,因此多线程处理数据时,能够用一些办法来避免使用锁,好比将数据的ID按照Hash算法取模分段,不一样的线程处理不一样段的数据。atom

2.CAS算法。eg:java的atomic包使用CAS算法来更新数据,而不须要加锁。

3.使用最少线程。

4.使用协程。协程:在单线程里实现多线程的调度,并在单线程里维持多个线程间的切换。

减小上下文切换实战:

经过减小线上大量WAITING的线程,来减小上下文切换的次数。

第一步:用jstack命令dump线程信息,看pid为3117的进程在作什么

sudo -u admin jstack 3117>/temp

第2步:统计全部线程分别处于什么状态

grep java.lang.Thread.State temp | awk '{print $2$3$4$5}'   | sort | uniq -c

原本应该截图的,不太方便直接把命令和结果赋值粘贴过来:

[tengfei.fangtf@ifeve ~]$ grep java.lang.Thread.State dump17 | awk '{print $2$3$4$5}'
    | sort | uniq -c
39 RUNNABLE
21 TIMED_WAITING(onobjectmonitor)
6 TIMED_WAITING(parking)
51 TIMED_WAITING(sleeping)
305 WAITING(onobjectmonitor)
3 WAITING(parking)

第三步:打开dump文件查看处于WAITING(onobjectmonitor)的线程在作什么,好比这本书的例子中,基本都是JBOSS的工做线程在await,说明JBOSS线程池里线程池里接受的任务太少;减小JBOSS的工做线程数,找到JBOSS的线程池配置信息,将maxThreads值调小。重启JBOSS,再dump线程信息,而后统计WAITING(onobjectmonitor)的线程,发现减小了不少。=====》由于每一次从WAITING到RUNNABLE都会进行一次上下文的切换。

=====》拓展:

什么使用须要用到jstack命令dump线程信息?

我印象很深的一次就是一个lisener的项目,上线一段时间后,某个队列忽然都阻塞了,消息不消费了,当时在listener admin控制台把阻塞的线程停用再启用,阻塞的消息很快都消费了,过了一段时间,这个项目的对应的另外一个队列阻塞,停用再启用以后阻塞的消息也都消费了,可是有一条unacked,当时用jstack命令dump了线程信息,而后在本地启动项目,在dump线程信息,异常的线程信息和正常的线程信息对比,排查问题。====》这个是由于esl链接有问题,是怎么发现是esl的链接有问题的。想不起来了,这个记得本身研究下,作一下记录。

死锁的时候须要用这个命令dump线程信息。

2.死锁

一旦出现死锁,业务是能够感知的,由于不能继续提供服务了,只能经过dump线程查看究竟是哪一个线程出现了问题。

===》工做中是否遇到过线上环境死锁?我听过同事遇到过,向他请教下他是怎么知道的,怎么排查的,怎么解决问题的,作好笔记。

避免死锁的方法:

1.避免一个线程同时获取多个锁。

2.避免一个线程在锁内同时占用多个资源,尽可能保证每一个锁只占用一个资源。

3.尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。====》sornarlint优化的时候,遇到一个锁的优化,后来由于优化会有潜在风险,没有优化,看看那个点,对比总结下。

4.对于数据库锁,加锁和解锁必须在一个数据库链接里,不然会出现解锁失败的状况。

3.资源限制的挑战

资源限制:在进行并发编程时,程序的执行速度受限于计算机硬件资源或软件资源。

硬件资源限制有带宽的上传/下载速度、硬盘读写速度和CPU的处理速度。

软件资源限制有数据库的链接数和socket链接数等。

资源限制引起的问题:并发执行的代码受资源限制串行执行,速度会更慢,增长了上下文切换和资源调度的时间。

若是解决资源限制的问题:对于硬件资源限制,能够考虑使用集群并行执行程序。对于软件资源限制,能够考虑使用资源池将资源复用。总之,根据不一样的资源限制调整程序的并发数。

java并发机制的底层实现原理:

java代码在编译后会变成java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终须要转化为汇编指令在CPU上执行,java中所使用的并发机制依赖于JVM的实现和CPU的指令。 1.volatile volatile是轻量级的synchronized,它在多处理开发中保证了共享变量的“可见性”。 volatile使用恰当的话,比synchronized使用和执行成本更低,它不会引发线程上下文的切换和调度。

先了解几个CPU术语:

未完待续。。。。

相关文章
相关标签/搜索