文档章节

Reentranlock FairSync NonFairSync

o
 ovirtKg
发布于 2016/09/01 12:44
字数 772
阅读 27
收藏 0

 

对于Reentranlock的用法,对比Synchronized多了 定时守候、可中断守候、公平和非公平。本文重点就Reentranlock 中的代码实现做一个分析。而对于其与Synchronize 区别可参考下文。

可以参考深入研究 Java Synchronize 和 Lock 的区别与用法http://my.oschina.net/softwarechina/blog/170859

 FairSync NonFairSync  两者都是java.util.concurrent包中同步类中如Semaphere,Reentranlock 等类中的内部类,两者继承自 AQS,而Reentranlock中的 两者代码如下所示,为独占模式。两者都实现了tryAcquire,与lock方法。

 

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

Reentranlock 根据参数,确定使用哪种同步器,默认是NonFairSync。从代码分析出,NonFairSync最大的特点是,调用lock时,会先尝试去获取资源,而获取不同,则通过父类的acquire(1)方法,调用各自子类的tryAcquire方法,如下。而对于NonFairSync,在一次执行父类Sync中的方法,在一次尝试获取资源。

然而对于FairSync的lock,直接调用acquire,少了一次直接获取的过程,接着调用子类的tryAcquire方法,当有资源空闲时,并不像NonFair 直接尝试get,而是先判断当前线程是否队列头部的线程,或者是空的queue,则尝试获取。否则判断当前线程是否是占用资源的线程。如果是,则将state+1,表示该线程调了多次lock,释放时要调同等次数的unlock,才能释放资源。


    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&  //当前Thread是否是head节点的next节点线程,因为公平的锁,按顺序获取资源
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

    接着上一步,两者都没有获取到资源时,将执行一样的流程,但是执行到tryAcqure方法时,会根据不同子类实现的来执行。

        如下代码,首先

  1.     addWaiter,,生成一个Exclusive模式的结点,并将当前结点加入到queque的尾部。如果原tail为null,也就是queque为null时,会cas一个new  Node,而后加到该node尾部。并做为新的tail。
  2.     而后会 执行acquireQueued方法,根据node的 predocessor,判断是否为head,如果是则执行tryAcquire,  获取成功后,将当前结点置为head,并将thread置为null,已经获得资源。
  3.    当node的prddocessor不为head时,或者获取失败,接着会根据waitStatus,执行相关操作,最终state置为Node.Signal,而后被阻塞,等着被unPark或者被中断。
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

 

而对于 Reentranlock 的其它功能如 中断守候,超时等,都是针对这些条件做了额外的操作。

© 著作权归作者所有

o
粉丝 3
博文 57
码字总数 48798
作品 0
景德镇
私信 提问
Java多线程系列之JUC锁 - ReentrantLock

一、ReentrantLock的介绍 ReentrantLock在源码中的解释是作为可重入互斥锁与synchronized有基本相同的行为和语义但是它在此基础上又扩展了其他的一些功能。ReentrantLock锁的线程持有者是上一...

老韭菜
2018/09/03
0
1
Java锁之ReentrantLock(一)

一、ReenTrantLock结构 图1-1 根据上图可以知道,ReenTrantLock继承了Lock接口,Lock接口声明方法如下: 方法名 说明 抛出异常 lock() 一直阻塞获取锁,直到获取成功 无 lockInterruptibl...

木木匠
2018/08/10
0
0
Java并发学习(十二)-ReentrantLock分析

What is ReentrantLock ReentrantLock,从单词字面上理解,就是可重入锁,他内部实现了两种锁的机制,公平锁与非公平锁,排他性的, 继承自AbatractQueuedSynchronizer,依靠着AQS里面的FIF...

anLA_
2017/12/01
0
0
ReentrantLock与公平锁、非公平锁实现

前言 最近开始读JDK源码,所有心得准备总结成一个专栏,JDK Analysis系列的第一篇,就从万众瞩目的ReentrantLock开始吧,而谈到ReentrantLock,就不得不说AQS,它是AbstractQueuedSynchroni...

rickiyeat
2017/10/22
0
0
JUC锁框架——Semaphore

Semaphore简单介绍 Semaphore是计数信号量。Semaphore管理一系列许可证。每个acquire方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;每个release方法增加一个许可证,这可能会释放一...

长头发-dawn
2018/09/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java中print、printf、println的区别

printf主要是继承了C语言的printf的一些特性,可以进行格式化输出 print就是一般的标准输出,但是不换行 println和print基本没什么差别,就是最后会换行

hellation_
28分钟前
0
0
spring在静态类中注入bean的的解释

@Componentpublic class ModelMapper {@AutoWiredprivate static AssignmentManager assignmentManager;public static void add(){a+b;}} 静态方法是属于类的,普通方法才属于...

无知的小狼
29分钟前
2
0
分而治之-归并排序

如果有1个数组,数组的左半部分和右半部分都已经排好序,如何将该数组合成1个有序的数组? 开辟1个同样大小的临时空间辅助我们完成归并过程,如下图 k:表示归并过程中,当前需要替换的原数组...

万山红遍
43分钟前
2
0
Linux修改时区的正确方法【修改时间,需要修改软连接,靠谱】

CentOS和Ubuntu的时区文件是/etc/localtime,但是在CentOS7以后localtime以及变成了一个链接文件 [root@centos7 ~]# ll /etc/localtime lrwxrwxrwx 1 root root 33 Oct 12 11:01 /etc/loca......

Airship
今天
1
0
《Netkiller Spring Cloud 手札》之 Master / Slave 主从数据库数据源配置

5.19.1. Master / Slave 主从数据库数据源配置 5.19.1.1. application.properties spring.datasource.master.driverClassName = com.mysql.cj.jdbc.Driverspring.datasource.master.url=j......

netkiller-
今天
50
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部