Java的锁

Posted CherryTab

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java的锁相关的知识,希望对你有一定的参考价值。

本人曾接手过一些很奇怪的代码,基本到处都是是volatile和硬加锁,说是为了安全,就不怕死锁和性能太差吗?其实我压根不想改这种东西了,既然能过code review那么说明什么问题了?我不会让自己成为这类人。

 

参考自

https://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651749434&idx=3&sn=5ffa63ad47fe166f2f1a9f604ed10091&chksm=bd12a5778a652c61509d9e718ab086ff27ad8768586ea9b38c3dcf9e017a8e49bcae3df9bcc8&scene=38#wechat_redirect

 

 

乐观锁和悲观锁

简单解释就是,悲观锁认为在一个线程使用数据的时候,一定会有别的线程来修改数据,所以在使用数据时候就加上一个锁,synchronizied和lock就是如此。

 

乐观锁是一种使用不直接加锁,当修改时再判断数据是否被其他线程修改之类的无锁编程。CAS,你不需要手动设置锁。

 

CAS很简单,只讲缺点

ABA问题

循环开销大

只能保证一个原子量

 

自选锁和适应性自旋锁

因为自旋锁缺点比较明显,就是cpu一直再切换,因此有了适应性自旋锁

 

 自选等待实际上只是减少cpu的切换性能浪费,将线程挂起也是占用着cpu的资源,因此现在为了避免过度等待也有不同的等待策略。

 

无锁,偏向锁,轻量级锁,重量级锁

上面我们介绍的CAS原理及应用即是无锁的实现。无锁无法全面代替有锁,但无锁在某些场合下的性能是非常高的。

 

偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价。

在大多数情况下,锁总是由同一线程多次获得,不存在多线程竞争,所以出现了偏向锁。其目标就是在只有一个线程执行同步代码块时能够提高性能。

 

是指当锁是偏向锁的时候,被另外的线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。

若当前只有一个等待线程,则该线程通过自旋进行等待。但是当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁升级为重量级锁。

 

公平锁和非公平锁

 

 

 

 

 

可重入锁和不可重入锁

 

 

 

当线程尝试获取锁时,可重入锁先尝试获取并更新status值,如果status == 0表示没有其他线程在执行同步代码,则把status置为1,当前线程开始执行。如果status != 0,则判断当前线程是否是获取到这个锁的线程,如果是的话执行status+1,且当前线程可以再次获取锁。而非可重入锁是直接去获取并尝试更新当前status的值,如果status != 0的话会导致其获取锁失败,当前线程阻塞。

 

 

 

 

 

 独享锁和共享锁

 ReentrantLock虽然有公平锁和非公平锁两种,但是它们添加的都是独享锁。根据源码所示,当某一个线程调用lock方法获取锁时,如果同步资源没有被其他线程锁住,那么当前线程在使用CAS更新state成功后就会成功抢占该资源。而如果公共资源被占用且不是被当前线程占用,那么就会加锁失败。所以可以确定ReentrantLock无论读操作还是写操作,添加的锁都是都是独享锁。

 

 

 

以上是关于Java的锁的主要内容,如果未能解决你的问题,请参考以下文章

Java的锁

Java中的锁

《Java并发编程的艺术》读后笔记-第五章 Java中的锁

java的锁机制

Java 实例级别的锁和类级别的锁

Java中的锁机制