Volatile和Synchronized的底层实现原理(java并发编程艺术的第二章)

一、
1、Volatile是java中的关键字,被它修饰的变量被称作是共享变量。这个共享变量具有“可见性”,可见性的意思是当有一个线程修改了这个变量的时候,其他的线程能读到这个修改的值。
2、Volatile被称作是轻量级的Synchronized。因为它不会产生由于请求锁而导致的阻塞,而且它不会引起上下文切换的问题。
二、Volatile的底层实现原理(也就是怎么样实现共享变量的可见性的)
1、对Volatile修饰的变量进行写操作的时候经过编译器编译后会产生一个具有Lock前缀的汇编代码,这个Lock前缀的指令就保证了volatile修饰的变量的共享可见性
2、Lock前缀指令的作用
(1)将当前处理器缓存行的数据写回到系统内存中
(2)这个写回内存的操作会是使得其他CPU里缓存了该内存地址的数据无效
3、解释上面的两条作用
(1)为了提高处理速度,处理器不直接跟内存进行通信,而是先将系统内存的数据读到内部缓存后再进行操作(我这里的理解是每个CPU都有自己的缓存),但操作完后不知道何时再写回内存。如果对声明了是volatile的变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据写回内存(以上操作就是第一个作用)
(2)但是就算是写回内存,如果其他的处理器缓存的值还是旧的,再执行计算操作就会出问题。所以在多处理器下,为了保证各个处理器的缓存时一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改(就是写操作),就会将当前处理器的缓存行设置为无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存中。
二、关于Synchronized笔记里有,这里主要说一下Synchronized的实现原理啊
1、代码块同步是使用monitorenter和monitorexit指令实现的。monitorenter插入在同步代码块的头,monitorexit插入在同步代码块的尾部。二者之间为要同步的代码块。当程序执行到monitorenter时候,就会去获取对象所对应的monitor的所有权,每个对象都有对应的monitor所有权,要是这个对象的monitor所有权被占用了,那么就是获取这个对象的锁了。
2、Synchronized用的锁是存放在Java对象头里面的。
3、锁的四种状态
无锁状态
偏向锁
轻量级锁
重量级锁
三、关于原子操作
1、所谓原子操作就是“不可中断的一个或一些列操作”,举例子就是说i++。当一个线程进行i++的时候,其他线程不可以同时进行这个操作,这就保证了原子操作。否则的话就不是原子操作了
2、处理器实现原子操作的方法
(1)通过总线锁
(2)通过缓存锁
3、java实现原子操作的方法
(1)使用循环CSA
(2)加锁(锁机制保证了只有获得锁的线程才能操作锁定的内存区域)
4、循环CSA的问题(具体看书)
(1)ABA问题
(2)循环时间厂开销大
(3)只能保证一个共享变量的原子操作

这一章我觉得最主要的就是Volatile的底层实现原来,Lock前缀指令的那两个作用

volatile和Synchronized的区别
1、volatile是告诉JVM当前变量在寄存器(线程自己的工作内存)中是不确定的,需要从主线程中获取。sychronized是锁定当前变量,只有当前线程可以访问该变量,其他线程将会被阻塞直到该线程完成变量操作位置。
2、volatile仅能是现在变量级别,而sychronized则可以使用在变量,方法和类的级别上
3、volatile仅能改变变量的修改可见性,而不能保证原子性。sychronized不仅可以保证修改的可见性,还保证了原子性
4、volatile不会造成线程阻塞,而sychronized会造成线程组赛

你可能感兴趣的:(技术)