zoukankan      html  css  js  c++  java
  • 并发编程总结5-JUC-REENTRANTLOCK-3(非公平锁)

    非公平锁和公平锁在获取锁的方法上,流程是一样的;区别主要表现在“尝试获取锁的机制不同”。“公平锁”在每次尝试获取锁时,都是采用公平策略(根据等待队列依次排序等待);而“非公平锁”在每次尝试获取锁时,都是采用的非公平策略(无视等待队列,直接尝试获取锁,如果锁是空闲的,即可获取状态,则获取锁)。

    一、获取非公平锁

    lock()

    NonfairSync类中实现

    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }

    先通过compareAndSet(0, 1)来判断“锁”是不是空闲状态。是的话,“当前线程”直接获取“锁”;否则的话,调用acquire(1)获取锁。

    acquire()

    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    公平锁和非公平锁,只有tryAcquire()函数的实现不同;即它们尝试获取锁的机制不同。

    nonfairTryAcquire()

    final boolean nonfairTryAcquire(int acquires) {
        // 获取“当前线程”
        final Thread current = Thread.currentThread();
        // 获取“锁”的状态
        int c = getState();
        // c=0意味着“锁没有被任何线程锁拥有”
        if (c == 0) {
            // 若“锁没有被任何线程锁拥有”,则通过CAS函数设置“锁”的状态为acquires。
            // 同时,设置“当前线程”为锁的持有者。
            if (compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        }
        else if (current == getExclusiveOwnerThread()) {
            // 如果“锁”的持有者已经是“当前线程”,
            // 则将更新锁的状态。
            int nextc = c + acquires;
            if (nextc < 0) // overflow
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }

    (01) 如果“锁”没有被任何线程拥有,则通过CAS函数设置“锁”的状态为acquires,同时,设置“当前线程”为锁的持有者,然后返回true。
    (02) 如果“锁”的持有者已经是当前线程,则将更新锁的状态即可。

    二、释放非公平锁

    非公平锁和公平锁在释放锁的方法和策略上是一样的。

    总结
    公平锁和非公平锁的区别,是在获取锁的机制上的区别。表现在,在尝试获取锁时 ——

    1、公平锁,只有在当前线程是CLH等待队列的表头时,才获取锁;

    2、非公平锁,只要当前锁处于空闲状态,则直接获取锁,而不管CLH等待队列中的顺序。

    3、当非公平锁尝试获取锁失败的时候,它才会像公平锁一样,进入CLH等待队列排序等待。

  • 相关阅读:
    sqlchemy self made
    scrapy 自定义图片路径保存,并存到数据库中
    关于scrapy下载文件重命名的办法以及对应url没有文件后缀的办法
    下载转码
    scrapy 下载图片 from cuiqingcai
    Scrapy框架学习
    字符串处理
    scrapy 日志处理
    sqlalchemy多对多查询
    sqlalchemy 多对多关系
  • 原文地址:https://www.cnblogs.com/guoliangxie/p/6767471.html
Copyright © 2011-2022 走看看