当前位置: 首页 > wzjs >正文

团购网站建设怎么样免费建站网站网页

团购网站建设怎么样,免费建站网站网页,logo123设计网,在线考试网站模板上一章讲完了独占非中断获取锁的源码,本章我们来讲一讲共享锁以及中断获取锁的源码。 源码: 共享获取锁: 首先我们要了解什么是共享锁,共享式获取与独占式获取最主要的区别在于同一时刻能否有多个线程同时获取到同步的状态。以…

上一章讲完了独占非中断获取锁的源码,本章我们来讲一讲共享锁以及中断获取锁的源码。

源码:

共享获取锁:

首先我们要了解什么是共享锁,共享式获取与独占式获取最主要的区别在于同一时刻能否有多个线程同时获取到同步的状态。以读写锁为例,在数据库中的读锁则是共享锁,可以允许多个线程同时访问这个资源,但是写锁则为独占锁也就是说只能允许一个线程在一个时间段访问这个资源。并且读锁和写锁是互斥的,也就是共享锁和独占锁是互斥的

上图可以看出对于共享锁可以允许多个线程访问当持有共享锁的时候独占线程后续则不能持有独占锁,同样的当独占锁持有锁的同时不允许共享锁持有。我们看一下ReentrantReadWriteLock锁源码

public class ReentrantReadWriteLock implements ReadWriteLock, Serializable {private static final long serialVersionUID = -6992448646407690164L;private final ReadLock readerLock;private final WriteLock writerLock;final Sync sync;
}

可以看出ReentrantReadWriteLock内部含有三个内部类一个是readerLock(读锁),一个是writerLock(写锁),一个是Sync(AQS子类)。那么其实readerLock与writerLock的api调用还是基于Sync的方法来实现的。

那么公用一个Sync 当进行读写锁的获取的时候如何达到读写互斥呢,原理就在于AQS的state变量,对于这个变量是int类型的,那么就将其分为两部分,高16位表示高 16 位表示读锁计数,低 16 位表示写锁重入次数,基于此可以区分当前锁是否有读锁和写锁,当进行读锁或者写锁获取判断的时候只需要看高16位和低16位值是否大于0就知道当前锁对象中是否含有读锁或者写锁,基于此来实现了读写互斥。

读写互斥我们说完了那么我们就来讲讲读锁也就是共享锁获取的源码解析:

        public void lock() {this.sync.acquireShared(1);}

可以看出读锁的lock获取是基于AQS的acquireShared方法来实现的。其中的参数与独占锁表示的一样也是获取同步资源的个数。

    public final void acquireShared(int var1) {if (this.tryAcquireShared(var1) < 0) {this.doAcquireShared(var1);}}

其中tryAcquireShared表示尝试获取锁,其中会返回当前锁的state值表示资源的剩余量,如果小于0则表示获取锁失败,会进入doAcquireShared方法中,并且tryAcquireShared也是交给子类去实现的

    private void doAcquireShared(int var1) {Node var2 = this.addWaiter(AbstractQueuedSynchronizer.Node.SHARED);boolean var3 = true;try {boolean var4 = false;while(true) {Node var5 = var2.predecessor();if (var5 == this.head) {int var6 = this.tryAcquireShared(var1);if (var6 >= 0) {this.setHeadAndPropagate(var2, var6);var5.next = null;if (var4) {selfInterrupt();}var3 = false;return;}}if (shouldParkAfterFailedAcquire(var5, var2) && this.parkAndCheckInterrupt()) {var4 = true;}}} finally {if (var3) {this.cancelAcquire(var2);}}}

分析上述源码,首先与独占锁一样先得到Node节点调用addWaiter方法进行初始化初始化方法的逻辑与独占锁初始化的一样上一章已经讲过,这里就不加赘述了。然后我们看与独占锁一样进入了一个死循环中,并且逻辑也几乎一样首先判断前驱节点是否为head节点,如果不是则不会尝试获取锁,是则获取锁。由此可见:几乎每个节点都不会与其他节点进行通信的,都是通过比较头节点来选择是否进行锁抢占。那么与独占锁的区别在于尝试获取锁的时候返回值不再是Boolean类型而是int类型原因是读锁是共享锁可以多个线程访问资源,而这里控制线程访问数量则是通过state的值来进行控制的。后续的逻辑与独占锁基本相同,如果返回的值大于0表明还有资源可以获取此时则会进行head头的设置,注意这里的head头设置采用了CAS锁的方式进行设置与独占锁不同,原因可能多个线程同时设置head头,而独占锁肯定只有一个线程来设置head头。而如果不是head头则会进行shouldParkAfterFailedAcquire方法的阻塞校验设置以及调用parkAndCheckInterrupt进入阻塞状态减少cpu资源的消耗。

我们可以看出共享锁与独占锁获取锁的方式大差不差区别点在于尝试获取锁的时候返回类型以及head头设置的时候需要加上CAS锁保证同步,并且同样的var4表示线程的中断状态但是并没有实质性的作用,因此这个方法也是无法进行中断的。接下来我们将讲述可以中断的获取锁的方法。

独占超时获取锁:

我们直接从ReentrantLock源码的tryLock来进行源码分析

    public boolean tryLock(long var1, TimeUnit var3) throws InterruptedException {return this.sync.tryAcquireNanos(1, var3.toNanos(var1));}

这里的参数多了一个TimeUnit类型的表示超时时间,也就是说这个获取锁是有一个时间限制的如果超时之后将会直接返回当前锁获取结果。我们可以看出其核心代码还是依赖于AQS的tryAcquireNanos方法

 public final boolean tryAcquireNanos(int var1, long var2) throws InterruptedException {if (Thread.interrupted()) {throw new InterruptedException();} else {return this.tryAcquire(var1) || this.doAcquireNanos(var1, var2);}}

可以看出首先就进行了线程中断的判断,如果中断标志为打开那么就会抛出异常来终止方法的进行。如果中断标志位为false则会进入以下两个方法tryAcquire和doAcquireNanos。其中tryAcquire则是交给子类去实现的方法。doAcquireNanos则是进入等待队列的方法。

    private boolean doAcquireNanos(int var1, long var2) throws InterruptedException {if (var2 <= 0L) {return false;} else {long var4 = System.nanoTime() + var2;Node var6 = this.addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE);boolean var7 = true;while(true) {boolean var9;try {Node var8 = var6.predecessor();if (var8 == this.head && this.tryAcquire(var1)) {this.setHead(var6);var8.next = null;var7 = false;var9 = true;return var9;}var2 = var4 - System.nanoTime();if (var2 > 0L) {if (shouldParkAfterFailedAcquire(var8, var6) && var2 > 1000L) {LockSupport.parkNanos(this, var2);}if (Thread.interrupted()) {throw new InterruptedException();}continue;}var9 = false;} finally {if (var7) {this.cancelAcquire(var6);}}return var9;}}}

进入方法之后首先判断是否当前时间小于0,小于则直接返回false。然后判断head是否为前驱节点并且尝试获取锁,如果都为true则会将head进行重新设置。此时设置head不需要CAS因为是独占锁。如果head头既不是前驱节点那么就会计算当前时间还剩余多少。如果剩余时间小于0那么则证明时间过期直接设置返回false,表示方法执行结束。如果时间还有那么就会进行阻塞判断,判断逻辑与独占非中断锁几乎一样都是先查看当前前驱节点的状态是否符合标准如果不符合则会重新选择前驱节点(将前驱节点剔除),同时判断所剩时间是否过于小,如果都符合的话则会进入阻塞,这里的阻塞与非中断阻塞不同,这里的阻塞设置了阻塞时间。

public static void parkNanos(Object var0, long var1) {if (var1 > 0L) {Thread var3 = Thread.currentThread();setBlocker(var3, var0);UNSAFE.park(false, var1);setBlocker(var3, (Object)null);}}

其中park方法则是阻塞方法,Unsafe.park则是阻塞方法。当出来之后也会判断当前线程是否中断标志为true,如果为true则会抛出异常。

                        if (Thread.interrupted()) {throw new InterruptedException();}

后续的方法则与不可中断的获取锁方法逻辑一样。

至此我们来总结一下可中断的超时获取锁与普通的获取锁的区别在哪里

1. 几乎每个方法都会先判断当前线程的中断标志位,并且做出对应的处理,这里与普通获取锁不同,普通获取锁只会记录而不会做出对应的逻辑处理

2.同时设置超时时间会在循环中进行时间判断如果时间剩余小于0则会直接返回当前的获取锁的结果值

至此独占,共享,可中断,含有超时时间的获取锁的方法源码解析都已经解析完毕。接下来我们讲一讲可重入锁的源码分析。

http://www.dtcms.com/wzjs/480911.html

相关文章:

  • 做的好看的pc端网站百度网盘客服中心电话
  • 科技网站设计公司排名如何引流推广
  • 网络求职做阿姨哪个网站好软文代发价格
  • 哈尔滨网站开发论坛刷网站关键词工具
  • 门户网站栏目建设网站权重划分
  • 句容建设质检站网站开发一个app需要多少钱?
  • 40平米服装店装修效果图无锡百度seo优化
  • 北京三原色ps网站近期网络营销的热点事件
  • 做网站在哪里租服务器宣传网站有哪些
  • vs做网站怎样加数据库北京网站优化页面
  • wordpress 多说 登陆不了百度上海推广优化公司
  • wordpress拖拽式主题seo黑帽优化
  • 如何用python做网站脚本语言成都十大营销策划公司
  • 秦州建设网站网络快速排名优化方法
  • 二手站网站怎做软文代写平台
  • 建设网站需要哪些素材sem是什么方法
  • 普通电脑可以做网站服务器吗网络服务器
  • 北京网站制作服务app拉新项目一手渠道商
  • 镜像网站怎么做排名一元手游平台app
  • 网站建设过程中需要注意的通用原则软件关键词排名
  • 榆林网站建设价格什么是搜索引擎推广
  • 做网站外包的公司好干嘛市场策划方案
  • 网站开发赚钱吗网站搜索排名优化
  • 域名备案后网站打不开广东深圳疫情最新
  • 链家网站开发技术百度搜索排名怎么靠前
  • 做ui要上那些网站关键词有哪些关联词
  • 网站建设教程浩森宇特刷排名seo
  • 上海企业注销流程苏州优化seo
  • html5网站建设平台电商网站商品页的优化目标是什么
  • 网站建设总流程图哪些平台可以打小广告