内置锁(隐式锁)和显示锁
- synchronized是jvm的锁,释放锁的过程不需要我们自己手动释放,jvm帮我们做了
- ReentrantLock(可重入锁),加锁、释放锁都是自己手动的
可重入锁
线程可以进入任何一个它已经拥有锁的同步代码块,讲的是一个已经上锁的函数,调用了一个也上锁的函数,内层的函数会自动获取外层函数的锁
ReentrantLock和synchronized都是可重入锁,可重入锁简化了并发编程的开发
synchronized锁优化
synchronized的锁升级是单向的
对象头
synchronized所用的锁是存储在对象头的,靠着monitorenter和monitorexit指令实现的,每个对象都会被分配一个monitor,获得对象的monitor,就获得了对象的锁
- Mark Word: 存储所得信息、对象的hashCode、gc分代年龄
- Kclass Word: 存储对象类型数据的指针(最开始指向方法区的类的信息那块,新版去掉方法去后指向元空间所属类的地址)
- Array Length: 数组长度(只有数组对象才有)
网上找的一个Mard Word的图,Mark Word存储信息会根据锁的状态而发生变化
偏向锁
标志位是01,和无锁状态一样,偏向第一个访问锁的线程,在没有其它线程抢占锁的情况下(也就是只有一个线程使用锁),jvm会给线程添加一个偏向锁,但是当有第二个线程来抢占锁,当前线程会被刮起,jvm会释放掉当前线程的偏向锁,锁会从偏向锁变为轻量级锁,偏向锁是用CAS实现的
自旋锁
自旋锁是针对线程切换的,线程阻塞会导致cpu从内核态进入用户态,频繁的阻塞和唤醒对CPU来说是一件负担很重的工作。很多对象锁的锁定状态只会持续很短的一段时间,例如整数的自加操作,在很短的时间内阻塞并唤醒线程显然不值得,为此引入了自旋锁;自旋锁是让等待线程去做一个无意义的循环,锁,如果竞争不到继续循环,循环过程中线程会一直处于running状态,但是基于JVM的线程调度,会出让时间片,所以其他线程依旧有申请锁和释放锁的机会
轻量级锁
一个对象虽然有多个线程要对它进行加锁,但是加锁的时间是错开的 通过自旋锁达到多个线程交替使用锁,不让线程进入阻塞状态,这个叫做轻量级锁;一旦两个或者两个以上的线程在同一时刻对一个资源进行争夺,jvm就会将轻量级锁变为重量级锁
重量级锁
早器java版本没有对synchronized做优化的时候,内置锁在java中被抽象成监视器锁(Minitor),监视器锁对应这操作系统的种的互斥量,这种同步方式的成本非常高,包括系统调用引起的内核态与用户态切换、线程阻塞造成的线程切换等
锁 | 优点 | 缺点 | 场景 |
---|---|---|---|
偏向锁 | 加锁、释放锁不消耗资源 | 不能拥有多个线程 | 适用于单线程 |
轻量级锁 | 线程交替使用锁,不会造成阻塞 | 没得到锁的线程会使用自旋锁造成cpu消耗 | 需要代码块内容执行快,追求响应快 |
重量级锁 | 不会使用自旋锁造成cpu消耗 | 线程阻塞,响应时间慢 | 同步代码块的内容执行慢,追求吞吐量大 |
悲观锁
悲观锁是指线程在修改数据的时候,总认为别的线程会修改数据,从而个数据(资源)上锁;简单点来说就是共享资源只能被一个线程使用,这个线程用完之后,其它线程才能获取到锁;
- 行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁就是悲观锁的思想
- Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现
- 多用于写的场景
乐观锁
参考博客:https://blog.csdn.net/qq_34337272/article/details/81072874
乐观锁是指线程在修改数据的时候,总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据
- 版本号机制:给数据表添加一个版本号,读的时候会读版本号,更新的时候线程读的版本号必须跟数据表的版本号相同才能完成更新操作,更新操作完成之后数据表的版本号加一
- CAS无所算法: Compare And Swap,有三个操作数:需要读写内存的值V,旧的预期值 A、拟写入的新值 B,当且仅当 V 的值等于 A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作)。一般情况下是一个自旋操作,即不断的重试
- 多用于读的场景
参考
参考博客: https://www.jianshu.com/p/36eedeb3f912
https://www.cnblogs.com/wade-luffy/p/5969418.html
https://blog.csdn.net/qq_34337272/article/details/81072874