在并发编程里面,锁我们经常使用。那么关于常用的锁,现在做一个总结。
区别
语法上:sysnchronized是关键字,源码在jvm里面。 lock是接口,源码是jdk实现。Synchronized退出同步代码块,锁会自动释放,而lock需要手动解锁。
功能上:两者都属于悲观锁,具备互斥同步锁重入。但是lock提供了sysnchronized不具有的公平锁,可打断,可超时等。
性能上:在没有竞争时候,synchronized是偏量锁,轻量级锁,在竞争激烈时候,lock性能好。
里面涉及的名词:
jvm:Java虚拟机,参考JVM结构 - 掘金 (juejin.cn)
sysnchronized:同步锁的一个关键字,可以添加在类上,锁住当前类,可以在方法上,锁住当前方法,可以在静态方法上面,锁住这个类的所有对象,可以在代码块上面(需要手动添加一个对象)锁住添加的对象。
Syncronized 的目的是一次只允许一个线程进入由他修饰的代码段,从而允许他们进行自我保护
synchronized作用在代码块时,它的底层是通过monitorenter、monitorexit指令来实现的。
经常遇到synchronized关键字和volatile关键字的特性进行对比,synchronized关键字可以保证并发编程的三大特性:原子性、可见性、有序性,而volatile关键字只能保证可见性和有序性,不能保证原子性,也称为是轻量级的synchronized
原子性:一个或者多个操作要么都不做,要么都要做
可见性:当一个线程对变量进行修改后,其他线程可以马上看到
有序性:按照代码先后顺序执行
悲观锁:认为在每次操作变量时候,都会被其他线程修改,所以每次操作都要加锁,线程占用占用锁,才能操作变量,每次只能一个线程操作,每次都要切换上下文,影响性能。(乐观锁:认为每次挫折其他线程都不会修改,即每次占用一个线程修改变量,失败后会不断尝试,所以不会加锁,在进行更新时候会查看是否被修改,不涉及上下文切换)
公平锁:多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,按照队列顺序得到锁。
非公平锁:多个线程去获取锁的时候,会直接去尝试获取,获取不到,再去进入等待队列,如果能获取到,就直接获取到锁。
synchronized的四种状态:(无锁->偏向锁->轻量级锁->重量级锁 )
无锁:修改在循环内进行,不断进行尝试修改,如果有冲突就退出,否则继续循环尝试。比如CAS
偏向锁:一段代码一种被某个线程占用,占用其他线程需要访问当前代码,才会释放锁。
轻量级锁:当锁是偏量锁时候,被其他线程访问会升级,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。
如当前只有一个等待线程,那么就会开始自旋等待。
重量级锁:当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁升级为重量级锁