读书一记

122 阅读3分钟

1:volatile

volatile实现的两条原则

a)volatile编译生成的lock指令会引起处理器缓存歇写回到主内存。

b)一个处理器的缓存写回到主内存会导致其他处理去的缓存失效。 


2:synchronized

java中的每一个对象都可以作为锁

对于普通同步方法,锁的是当前实例对象

对于静态同步方法,锁的是当前类的class对象

对于同步方法块,锁的是synchronized括号里配置的对象


方法块的同步使用moniterenter和moniterexit实现,而同步方法使用另外一种方式实现,细节在jvm中没有详细的说明


moniterenter和moniterexit在代码编译的时候会插入到同步代码块的开始和结束位置。


3:Java对象头

synchronized用的锁是存在java对象头里面的,32位的虚拟机中,1字宽等于4字节。

如果对象是数组类型,则虚拟机使用3个字宽存储对象头

如果对象不是数组类型,则虚拟机使用2个字宽存储对象头


mark word默认存储对象的hashcode,分代年龄和锁标记,下面是mark word示意图,



4:偏向锁

a)大多数情况下,锁不仅不存在多线程竞争,而且总是由同一个线程获得,为了让线程获取锁的代价更低,引入了偏向锁。

b)偏向锁使用了一种等到竞争出现时才会释放锁的机制,当其他线程有竞争偏向锁时,偏向锁的线程才会释放锁。

c)偏向锁在java6和java7中默认是打开的,可以通过设置jvm参数-xx:UseBiasedLocking=false来关闭。

5:轻量级锁

a)线程执行同步块之前,jvm先在当前线程的栈桢中创建用于存储锁记录的空间

b)将对象头中的mark word复制到锁记录中

c)线程尝试修改对象头中的mark word替换为指向锁记录的指针,如果成功,获得锁,如果失败,就表明存在竞争,当前线程使用cas自旋来获取锁

自旋会消耗CPU,为了避免无用的自旋,锁会升级成重量级锁。

6:锁优缺点


7:处理器如何实现原子操作

a)使用总线锁,就是使用处理器提供的一个lock信号,当处理器在总线上输入此信号,其他处理器的请求将会被阻塞,那么改处理器就可以独占共享内存。

b)使用缓存锁定,内存区域如果被缓存在处理器的缓存行中,并且在lock锁定期间,缓存一致性会阻止同时修改由两个以上处理器缓存的内存数据,其他的处理器回写已被锁定的缓存行数据时,会使缓存行无效。

两种情况不会使用缓存锁定

       a:操作的数据不能缓存在处理器内部,或操作的数据跨多个缓存行时,会使用总线锁定

       b:处理器不支持缓存锁定



如果你觉得每天一记有用,或者想获取更多内容,请扫下面二维码~~~


扫一扫 关注我的公众号

如果你想要跟大家分享你的文章,欢迎留言投稿~

如果你喜欢,请留下你的赞哦