本文为原创,如需转载请注明来处便可。java
现代jdk juc包源码解读算法
使用场景分析编程
使用场景解读api
互斥同步(mutual exclusion & synchronization)是常见的一种并发正确性保障手段。同步是指多个线程并发访问共享数据时,保证共享数据在同一时刻只能被一个线程(或者是一些,使用信号量的时候)使用。
互斥是实现同步的一种手段,如临界区,互斥量,信号量都是主要的互斥实现方式。
互斥是因,同步是果。互斥是方法,同步时目的。安全
最基本的互斥实现手段就是synchronized关键字。synchronized关键字通过编译以后,会在同步块的先后分别造成monitorenter和monitorexit字节码指令,这两个字节码都须要一个reference类型的参数来指明锁定和解锁的对象。若是Java程序中的synchronized明确指定了对象参数,那就是这个对象的reference,若是没有明确指定,那就根据synchronized修饰的是实例方法仍是类方法,去取对应的对象实例或class对象来做为锁对象。架构
在执行monitorenter指令时,首先要尝试获取对象的锁。若是这个对象没有被锁定,或者当前线程已经拥有了那个对象的锁,把锁的计数器加1,相应的,在执行monitorexit时,将计数器减1,当为0时,锁就被释放。若是获取锁失败,那么当前线程就要阻塞等待,直到对象锁被另外一个线程释放。并发
TODO:【探究】探究reentrantlock锁(能够和其余类型的锁一块儿总结研究)【源码级别】 TODO:【探索】深刻探索juc包【源码级别】
乐观并发策略得益于硬件指令集的发展,硬件保证一个从语义上看起来须要屡次操做的行为只须要一条处理器指令集就能够完成,以下:函数
加载连接/条件存储(LL/SC)源码分析
cas指令须要3个操做数,分别是内存位置(再Java中能够简单的理解为变量的内存地址,用V表示),旧的预期值(A),和新值(B)。CAS指令执行时,当且仅当V的值符合旧的预期值A时,处理器用B更新A的值,不然不执行更新,但不管是否更新,返回的都是V的旧值。上述操做是一个原子操做。
TODO:【探索】从硬件指令集的角度探索cas的原子性。cas操做不是完美的,存在这样一个逻辑漏洞,简称 “ABA” 问题:
一个线程one从内存位置V中取出A,这时候另外一个线程two也从内存中取出A,而且two进行了一些操做变成了B,而后two又将V位置的数据变成A,这时候线程one进行CAS操做发现内存中仍然是A,而后one操做成功
TODO:【探索】cas操做使用场景分析。
若是一个方法自己就不涉及共享数据,那就天然无需同步措施来保证正确性。
可重入代码:
##
这种代码也叫作纯代码,能够在代码执行的任什么时候刻中断它,转而去执行另一段代码(包括递归调用它自己),而在控制权返回后,原来的程序不会发生任何错误。
##
全部的可重入代码都是线程安全的,可是并不是全部线程安全的代码都是可重入的。可重入代码都有一些共同的特征,如不依赖堆上共享数据和公共的系统资源,用到的状态量是从参数传入,不调用非可重入的方法等。
##
能够经过简单的原则来判断是否可重入性:若是一个方法,他的返回结果是能够预测的,只要输入了相同的数据,就能够返回相同的结果,那么他就能够知足可重入的要求,固然也就是线程安全的。
线程本地存储:
##
java.lang.ThreadLocal类能够实现线程本地存储的功能。每个线程的Thread对象都有一个ThreadLocalMap对象,这个对象存储了以 ThreadLocal.threadLocalHashCode为键,以本地线程变量为值得K-V值对,ThreadLocal对象就是当前线程的ThreadLocalMap访问入口,每个ThreadLocal对象都包含了独一无二的threadLocalHashCode值,就能够找到对应的本地线程变量。
##
大部分使用消费序列的架构模式都会使用线程本地存储。
TODO:【探究】详细探究ThreadLocal原理及其源码实现,必要的话单开一个po。
TODO:【延申】尝试探究消息服务队列的线程模型以及消息架构。【参考rocketMQ,KAFKA】
TODO:【延申】探索本地线程存储的使用场景,并解读。
参考: 《深刻理解Java虚拟机》第二版 《Java并发编程之美》 《rocket mq实战》