Synchronized : 称为重量级锁,经过优化后,也没那么重了
一、CAS
1、CAS:Compare and Swap, 翻译成比较并交换。
2、java.util.concurrent包中借助CAS实现了区别于synchronouse同步锁的一种乐观锁
3、CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
二、锁的升级和对比
偏向锁、轻量级锁、重量级锁适用于不同的并发场景:
- 偏向锁:无实际竞争,且将来只有一个申请锁的线程会使用锁。有其他线程来竞争,就撤销偏向锁;
- 轻量级锁:无实际竞争,多个线程交替使用锁;允许短时间的锁竞争。不会造成阻塞,存在竞争,转为重量级锁
- 重量级锁:有实际竞争,且锁竞争时间长。会阻塞
三、自旋锁:可以减少线程阻塞造成的线程切换(包括挂起线程和恢复线程)。
自旋:不直接阻塞自己,而是自旋(空等待,比如一个空的有限for循环)一会
四、锁分配和膨胀过程
Volatile:轻量级的synchronized
一、volatile的实现
如果对声明了volatile的变量进行写操作,JVM会向处理器发送一条Lock前缀的指令,
两条实现原则:
(1)Lock前缀指令会引起处理器缓存写会到内存;
(2)一个处理器的缓存回写到内存会导致其他处理器的缓存无效:
处理器使用嗅探技术保证它的内部缓存、系统内存和对其他处理器的缓存的数据在总线上保持一致(缓存一致性协议),党处理器发现自己缓存对应的内存地址被修 改,就会将当前处理器的缓存行设置为无效,会重新从系统内存中把数据读到处理器缓存里。
intel的手册对lock前缀的说明如下:
1、确保对内存的读-改-写操作原子执行。
在Pentium及Pentium之前的处理器中,带有lock前缀的指令在执行期间会锁住总线,使得其他处理器暂时无法通过总线访问内存。很显然,这会带来昂贵的开销。从 Pentium 4,Intel Xeon及P6处理器开始,intel在原有总线锁的基础上做了一个很有意义的优化:如果要访问的内存区域(area of memory)在lock前缀指令执行期间已经在处理器内部的缓存中被锁定(即包含该内存区域的缓存行当前处于独占或以修改状态),并且该内存区域被完全包含在单个缓存行(cache line)中,那么处理器将直接执行该指令。由于在指令执行期间该缓存行会一直被锁定,其它处理器无法读/写该指令要访问的内存区域,因此能保证指令执行的原子性。这个操作过程叫做缓存锁定(cache locking),缓存锁定将大大降低lock前缀指令的执行开销,但是当多处理器之间的竞争程度很高或者指令访问的内存地址未对齐时,仍然会锁住总线。
2、禁止该指令与之前和之后的读和写指令重排序。
3、把写缓冲区中的所有数据刷新到内存中。