并发调试及jdk8的并发新支持

并发的调试较单线程调试更复杂,且并发的问题不一定能复现,

1、介绍eclipse的条件断点

在加断点的地方,右键选择条件断点:

设置进入断点的条件:

 

 

案例:ArrayList(线程不安全)并发添加元素的越界的调试分析:

设置条件断点:

线程1越界后,抛出异常,终止运行,线程0继续运行:

2、使用jstack -l pid:分析线程锁情况

 如,可以看到java的死锁的情况。死锁介绍

3、java8对并发的新支持

1、LongAdder

先说下AtomicLong。在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。实现方式是内部有个volatile  value 变量,当多线程并发自增,自减时,均通过自旋的cas 指令从机器指令级别操作保证并发的原子性。AtomicLong中有个内部变量value保存着实际的long值,所有的操作都是针对该变量进行。也就是说,高并发环境下,value变量其实是一个热点,也就是N个线程竞争一个热点。

LongAdder的基本思路就是分散热点,将value值分散到一个数组中,不同线程会命中到数组的不同槽中,各个线程只对自己槽中的那个值进行CAS操作,这样热点就被分散了,冲突的概率就小很多。如果要获取真正的long值,只要将各个槽中的变量值累加返回。有点像锁优化中减小锁的粒度,空间换时间,如jdk7中的ConcurrentHashMap中的“分段锁”类似思想。

LongAdder来说,内部有一个base变量,一个Cell[]数组。
base变量:非竞态条件下,直接累加到该变量上,和AtomicLong类似,
Cell[]数组:竞态条件下,累加个各个线程自己的槽Cell[i]中值;             即:value=base+∑i=0nCell[i]

可以参考:https://segmentfault.com/a/1190000015865714

2、CompletableFuture

 先说下Future和Callable实现了用于阻塞式获取结果,Future.get()介绍是等到有结果返回,是阻塞的。

方法:String java.util.concurrent.Future.get() throws InterruptedException, ExecutionException

注释:Waits if necessary for the computation to complete, and then retrieves its result.

CompletableFuture是当任务完成后得到通知,自动调用一些回调方法,执行其他的操作,避免了任务的阻塞,是Future的增强。使用介绍可以参考:https://www.jianshu.com/p/6bac52527ca4

3、StampedLock

ReentrantReadWriteLock使得多个读线程同时持有读锁(只要写锁未被占用),而写锁是独占的。

但是,在读线程非常多,写线程很少的情况下,很容易产生“饥饿”问题,

StampedLock是读写锁的改进,读不阻塞写,Optimistic reading(乐观读模式)是一种优化的读模式。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值