并发编程常见的几种工具
Synchronized、ReentrantLock、CAS
Synchronized锁和ReentrantLock最本质的区别是二者的实现方式:
Synchronized锁是通过字节码实现的,即加monitorenter和monitorexit
ReentrantLock是AQS的实现,其加锁的方式是基于Unsafe包下面的CAS实现的
在早期版本的JDK中,Synchronized是重量级锁,性能不佳,但是随着新版本JDK通过锁自旋、锁升级等优化,性能已经有所提升,已经不把性能作为选择锁类型的主要因素了
ReentrantLock是java代码实现锁,其底层使用的是volatile+unsafe(可见它在源码的层面上并非真正的锁),因此比Synchronized多了很多能力,包括:
公平锁和非公平锁
阻塞获取锁
中断获取锁
通过Condition实现的更灵活的条件队列
丰富的api用于获取锁状态
CAS则不是锁,是unsafe包下面的一套native方法,它的含义是compareAndSet,本质上是一个原子操作,它也是ReentrantLock、ConcurrentHashMap等并发模型的底层实现,但是JDK9以后是不推荐使用unsafe的了,很多实现都切换到了新的VarHandle包
unsafe与varhandle
sun.misc.Unsafe
和 java.lang.invoke.VarHandle
都是 Java 中用于执行底层内存操作和原子操作的机制。它们的主要目标都是为库开发者(如 java.util.concurrent
包的实现者)提供构建高性能、无锁数据结构的基础能力
相比于unsafe,varhandle的安全性更高,例如不能突破java的一些语法限制(final不再可以被修改),同时提供更多CAS操作
volatile
volatile也是字节码层面的并发控制手段,其能力主要包括:
可见性保证:通过字节码增加的写回操作,要求CPU写缓存的操作必须同步刷新内存,并通过总线广播给其他线程,标记为已修改状态,在其他线程使用其值之前先从内存中重新刷新该值
有序性保证:通过增加内存屏障,避免指令重排序
hashCode()与equals()的区别与联系
hashCode是语法约束上的相等,equals是业务上的相等
hashCode方法是HashSet、HashMap等集合计算哈希散列的方法,当两个对象hashCode结果相等,意味着这两个对象在HashSet中是冲突的,即使这两个对象可能并不是一个
而equals常常被用于重写逻辑并进行业务相等的比较,当我们重写了equals但不重写hashCode,有可能出现业务相等但是计算哈希散列不等的情况,导致使用HashMap或HashSet存储并判断isExist时出现问题
评论区