作者: 红烧鸡翅膀_我喜欢吃 | 来源:发表于2020-03-04 12:35 被阅读0次

lock

synchronized & ReentrantLock

一、synchronized 

版本1.6为分割,

之前只是重量锁,使用mointor enter和exit指令集实现(CPU原语),等待时挂起线程,用户态切换成内核态,由操作系统管理。

之后改版优化:无锁 =》偏向锁 =》(CAS)轻量锁 =》重量锁

https://www.cnblogs.com/wzj4858/p/8215369.html

线程获取一个锁对象,去锁对象的头部markword读取是否有线程占用

1、如果没有就通过CAS更新该值(占有对象),每次加锁时只需判断对象里锁的线程id是否是自己就ok(偏向锁);

2、如果有其他线程已经使用了偏向锁,看其他线程是否还活跃,如果不活跃则取而代之,自己获得锁(依旧是偏向锁),否则升级为轻量锁,通过自旋的的方式去尝试获得锁(固定或自适应的次数去CAS),获取成功加轻量锁,自旋完成仍无法获取锁则升级为重量锁。

3、如果有线程在使用偏向锁,也有线程在使用自旋(轻量),自己直接使用重量锁,进入内核状态,挂起等待操作系统

------------------------

Synchronied 1.6之前比较重,比不过reetrantlock,1.6后反超。

reetrantlock使用CAS,可以设置公平锁和非公平锁(构造函数参数设置)默认非公 ; Sy只能非公平

Synchronied 释放后,所有其他等待线程和正好进来的线程都有机会获取锁;Reet只有等待队列的第一个和正好进来的有机会获取。

reetrantlock实现底层AQS+CAS,CountDownLatch底层也是AQS

https://blog.csdn.net/fuyuwei2015/article/details/83719444

-------------------------

二、hashmap的1.8

1、链表大于8的时候变成红黑树

2、之前的尾插变成了头插,解决了循环取值的问题(扩容导致)

https://www.jianshu.com/p/0df1f25139e4

------------------

ConcurrentHashMap的 1.8,性能提升

锁粒度变细,(之前在桶上加锁,用reetrantlock),改用synchronied在桶的每个节点上加。https://www.cnblogs.com/yangfeiORfeiyang/p/9694383.html

--------------------------------------------------------------

三:锁削除

锁削除是指虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行削除。锁削除的主要判定依据来源于逃逸分析的数据支持,如果判断到一段代码中,在堆上的所有数据都不会逃逸出去被其他线程访问到,那就可以把它们当作栈上数据对待, 认为它们是线程私有的,同步加锁自然就无须进行。比如(只是说明概念,但实际情况并不一定如例子)在线程安全的环境中使用stringBuffer进行字符串拼加。则会在java文件编译的时候,进行锁销除。

四:锁粗化 太零散反而不如整体加锁

原则上,我们在编写代码的时候,总是推荐将同步块的作用范围限制得尽量小——只在共享数据的实际作用域中才进行同步,这样是为了使得需要同步的操作数量尽可能变小,如果存在锁竞争,那等待锁的线程也能尽快地拿到锁。大部分情况下,上面的原则都是正确的,但是如果一系列的连续操作都对同一个对象反复加锁和解锁,甚至加锁操作是出现在循环体中的,那即使没有线程竞争,频繁地进行互斥同步操作也会导致不必要的性能损耗。如果虚拟机探测到有这样一串零碎的操作都对同一个对象加锁,将会把加锁同步的范围扩展(锁粗化)到整个操作序列的外部。

相关文章

网友评论

      本文标题:

      本文链接:https://www.haomeiwen.com/subject/bxjmlhtx.html