java


java 并发编程的艺术 方鹏飞 阿里

并发编程的挑战

  • 查看线程信息

    • 用jstack命令dump线程信息,看看pid为3117的进程里的线程都在做什么。
      • sudo -u admin /opt/ifeve/java/bin/jstack 31177 > /home/tengfei.fangtf/dump17
      • grep java.lang.Thread.State dump17 awk ‘{print $2$3$4$5}’ sort uniq -c
    • 打开dump文件查看处于WAITING(onobjectmonitor)的线程在做什么。发现这些线程基本全是JBOSS的工作线程,在await。说明JBOSS线程池里线程接收到的任务太少,大量线程都闲着。
    • WAITING的线程少了,系统上下文切换的次数就会少,因为每一次从WAITTING到RUNNABLE都会进行一次上下文的切换。 >Q: 为什么 waiting状态的要去切换一下?看一下是否已经不waiting了吗?
  • 介绍避免死锁的几个常见方法

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

    • 硬件资源限制有带宽的上传/下载速度、硬盘读写速度和CPU的处理速度。软件资源限制有数据库的连接 数和socket连接数等
    • 对于硬件资源限制,可以考虑使用集群并行执行程序。对于软件资源限制,可以考虑使用资源池将资源复用。比如使用连接池将数据库和Socket连接复用,或者在调用对方webservice接口获取数据时,只建立一个连接。

     Java并发机制的底层实现原理

  • Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和CPU的指令。

  • volatile的定义与实现原理

    • volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。如果volatile变量修饰符使用恰当的话,它比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换和调度。
    • instance = new Singleton(); // instance是volatile变量

      啥?为啥instance就是volatile变量

    • volatile干了什么?
      • 0x01a3de1d: movb $0×0,0×1104800(%esi);0x01a3de24: lock addl $0×0,(%esp);
      • 有volatile变量修饰的共享变量进行写操作的时候会多出第二行汇编代码,通过查IA-32架 构软件开发者手册可知,Lock前缀的指令在多核处理器下会引发了两件事情[1]。 1)将当前处理器缓存行的数据写回到系统内存。 2)这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。