最近又拿起了并发编程的艺术又看了一遍, 随着经验的增长,每次看都有一定的收获,每次都觉得理解的比之前要透彻一点, 故记录下此次复习的一些收获。
在多线程中除了synchronized,volatile应该是最为关键的知识点了。
原子性
先说明下原子性,我之前一直对这个概念,甚至原子性是谁的特性都不是很清楚。 拿volatile int i++计算来说明,++计算其实包含了两个动作,先读然后改,那么共享变量i的这两个操作 会被不同的处理器同时执行,是否可以理解为如果控制在同一个处理器中执行两个操作就满足原子性呢,这里我需要求助一下。
Java中实现原子操作有两种 1: synchronized,2: CAS
可见性
JMM(java memory model)中可将内存抽象为两块,一块是主内存,一块就是线程私有的本地内存。
线程私有的本地内存主要包含以下几块:寄存器,写缓冲区,缓存等。 当处理器写完volatile修饰的共享变量后,就会主动刷新主内存中的变量值, 并通知其他线程刷新本地缓存中的该变量。
指令重排序
JMM和处理器都会针对jvm生成的指令进行重排序,来提供效率。 比如说初始化两个无关痛痒的变量,两个指令先后执行对逻辑是没有影响的,那么初始化的指令就可能不是按照代码中的顺序来执行。 而volatile修饰的变量,为了防止指令重排,会在共享变量操作的前后加上内存屏障(memory barrier), 具体有loadStore, loadload, storestore, storeload四种,
java的多线程中由AQS(bstractQueueSynchronizer)来进行维护, 简单介绍下AQS,按照英文名翻译过来就是抽象的队列式同步器, 其主要维护了两个东西,一个volatile修饰的state,另外一个FIFO的同步队列, 又叫CLH同步队列。 所有的锁都会去实现该接口,并在内部类中实现其定义的获取锁以及释放锁的方法。
其他一些琐碎的知识点
java中有两种资源共享方式:
- 独占式(Exclusive) 如ReentrantLock
- 共享式(Share) 如CountDownLatch,CyclicBarrier以及semaphore
锁降级
当写锁将要释放的时候,加上读锁,这样就完成了一次锁的降级。