专业的JAVA编程教程与资源

网站首页 > java教程 正文

java编程进阶之路:回归锁的本质,探索分布式锁之源头

temp10 2024-11-22 20:54:27 java教程 13 ℃ 0 评论

开篇引论

众所周知,现在分布式应用越来越广泛,尤其是现在随着"中台"的搭建,分布式显得尤为重要,小到关乎应用的性能,大到影响一个企业的未来。在现在这个互联网飞速发展的时代,如果你所在的企业还未能引入"中台"的概念,那么你可以考虑一下今后的打算了。就算你用不着为企业着想,也要为自己的职业生涯负责。

都知道现在分布式锁应用越来越多,实现方式也是花样百出:

java编程进阶之路:回归锁的本质,探索分布式锁之源头

文章链接:

Redis分布式锁的实现方式之一(基于springboot项目搭建)

Zookeeper分布式锁实现方式之一

掌握分布式事务锁,这个大厂实战订单锁你一定要会

有了结果我们就应该追溯下源头,分布式锁的概念最早应该起源于synchronized与Lock的应用。只是后来这两种都无法满足分布式应用的时候,人们才逐渐引入了后来的分布式锁。


本文我们着重剖析下synchronized与Lock。

区别:

1.首先synchronized是java内置关键字,在jvm层面,Lock是个java接口,是基于JDK层面实现的,通过这个接口可以实现同步访问;

2.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁 c 调用wait()方法释放锁,Lock必须要在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;

3.用synchronized的两个线程,如果线程a拿到了锁执行代码块,b只有等待a代码块执行完毕或则a主动释放锁。此时,如果线程a阻塞的话,b会一直等待下去。

但是如果使用Lock锁,线程b就不一定会一直等待下去,如果尝试获取不到锁,线程b可以在指定时间内结束或则同步结束返回false未拿到锁。

4.synchronized和Lock特性比较

5.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。

6.synchronized无法判断线程获取到锁,而Lock则可以通过(ReentrantLock)得知线程有没有成功获取到锁。

使用场景:

synchronized

占有锁的线程执行完了该代码块,然后释放对锁的占有;

占有锁线程执行发生异常,此时JVM会让线程自动释放锁;

占有锁线程进入 WAITING 状态从而释放锁,例如在该线程中调用wait()方法等。

Lock

在使用synchronized关键字的情形下,假如占有锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,那么其他线程就只能一直等待。这会极大影响程序执行效率。

因此,就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间 (解决方案:tryLock(long time, TimeUnit unit)) 或者 能够响应中断 (解决方案:lockInterruptibly())),这种情况可以通过 Lock 解决。

Lock 继承关系

锁应用实操

1:两个线程获取锁,a先拿到锁,b再去拿锁:

运行结果如下:

2:两个线程尝试获取锁,a先尝试拿到锁,b在尝试去获取锁:

运行结果如下

3:两个线程尝试制定时间内去获取锁,a尝试2秒,拿到锁之后睡眠3秒,b在去尝试获取锁:

可见b无法拿到锁:

4:两个线程尝试制定时间内去获取锁,a尝试4秒,拿到锁之后睡眠3秒,b在去尝试获取锁:

尝试时间改为4秒后,睡眠3秒,对线程b就可以拿到了锁:

同学们可以实际运行下,"纸上得来终觉浅,绝知此事要躬行"。只有实际跑一下,才会有更深的理解,可能还会有意想不到的 收获~

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表