08经典问题答案记录-锁

08经典问题答案记录-锁

锁的分类

悲观锁与乐观锁

悲观锁和乐观锁是一种广义的概念

当一个线程使用数据时,悲观锁总是认为其它线程也会过来修改这个数据。为了保证数据安全,其采用的是一种先加锁再访问的策略,其它线程要想也访问该数据则被阻塞等待、直到其获取到锁才可以访问

synchronized锁就是悲观锁

synchronized,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行

乐观锁,认为在使用数据的过程中其它线程不会修改这个数据,故不加锁直接访问。而当该线程需要提交更新、修改时,才会判断该数据在此期间有没有被其它线程更新、修改。如果其它线程确实没有修改,则该线程直接写入完成更新;反之如果该数据已经被其它线程更新、修改,则该线程将放弃本次数据的更新提交操作以避免出现冲突,并通过报错、重试等方式进行下一步处理

CAS算法就是乐观锁的实现

CAS算法

伪代码

do{
    1. 读取变量值,记为E。用于写入修改时,判断该变量是否被修改
    2. 使用读到的变量值E,计算该变量的新值,记为U
} while( !CAS(变量内存地址,EU) )
CAS算法的缺陷
ABA

简单来说,就是变量在过程被读取后由A被修改为B再修改回A,对于CAS是没变的但是却发生了变化

解决方法
可以通过给变量附加时间戳、版本号等信息来解决

CPU占用

如果CAS操作一直不成功会一直循环,浪费CPU资源

只能保证一个对象的原子性

当对多个变量进行操作时,CAS算法无法保证原子性。为此Java提供了一个AtomicReference类,可以通过组合的方式将多个变量封装为一个对象再使用CAS算法

自旋锁与阻塞锁

我们都知道CPU唤醒或者阻塞线程时,是有上下文切换的开销,若临界区的范围不是很大,在多核处理器中使用自旋锁是ok的
缺点:若临界区很耗时,使用自旋锁随着时间的推移会有很多的性能问题
优点:在一定程度上,自旋可以提供效率,JDK中的atomic采用了自旋锁

阻塞锁是指当线程尝试获取锁失败时,线程进入阻塞状态,直到接收信号后被唤醒.(线程的状态包括新建、就绪、运行、阻塞及死亡)在JAVA中,能够唤醒阻塞线程的操作包括Object.notify, Object.notifyAll, Condition.signal, LockSupport.unpark(JUC中引入)

阻塞锁的优点是在线程获取锁失败后,不会一直处于运行状态(占用CPU), 因此在竞争激烈的情况下, 阻塞锁的性能将明显优于自旋锁

https://blog.csdn.net/seulzz/article/details/113741650

锁的几种状态

无锁,偏向锁,轻量级锁,重量级锁
只能逐一升级,不能降级

(1)无锁:适用于单线程
(2)偏向锁:适用于只有一个线程访问同步块的情况,因为多个线程同时访问同步块,给某一个线程特权是不合理的
(3)轻量级锁:竞争不是太多,循环等待消耗CPU资源的线程的数量在可接受的范围(4)重量级锁:多个线程同时竞争资源,只让一个线程运行,其余的线程都阻塞

可重入锁和不可重入锁

从代码实现来看,可重入锁增加了两个状态,锁的计数器和被锁的线程,实现基本上和不可重入的实现一样,如果不同的线程进来,这个锁是没有问题的,但是如果进行递归计算的时候,如果加锁,不可重入锁就会出现死锁的问题。

所以这个不可重入是对同一个线程而言,能否第二次获取锁,下面是另一篇博客总结的:

可重入锁:可以再次进入方法A,就是说在释放锁前此线程可以再次进入方法A(方法A递归)。
不可重入锁(自旋锁):不可以再次进入方法A,也就是说获得锁进入方法A是此线程在释放锁钱唯一的一次进入方法A。
那这两种锁除了在可能会导致死锁方面的区别外,效率有差别了,我就利用Curator做了一个实验,实验的代码如下:
首先可重入锁的关键代码逻辑非常简单,而且使用了Atomic原子操作,效率非常高,但是不可重入锁代码量非常大,为了实现一个类似于Semaphore的工具,进行很多的判断,效率非常低,有兴趣的可以升入研究下这两种锁。

结论
重入锁和不可重入锁主要的差别在对相同线程是否能够重复获取,从效率来说,不可重入锁效率更高,当然这个是用Curator client测试,其代码实现也很复杂,可以试试用其他的工具测一下两者的区别

公平锁和非公平锁

互斥锁和共享锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值