我是靠谱客的博主 谦让皮带,最近开发中收集的这篇文章主要介绍公平锁与非公平锁什么是公平锁什么是非公平锁源码分析总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

公平锁与非公平锁

  • 什么是公平锁
    • 概念
    • 优点
    • 缺点
    • 图示
  • 什么是非公平锁
    • 概念
    • 优点
    • 缺点
    • 图示
  • 源码分析
    • 公平锁
    • 非公平锁
  • 总结

什么是公平锁

概念

公平锁是指多个线程按照申请锁的顺序来获得锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁。

优点

等待锁的线程不会饿死。

缺点

整体吞吐效率比非公平锁要低,等待队列中除第一个以外的线程都会阻塞,CPU唤醒阻塞线程的开销比非公平锁要大。

图示

在这里插入图片描述

什么是非公平锁

概念

非公平锁是多个线程加锁时直接尝试获得锁,获取不到才会进入等待队列的队尾等待。但如果此时锁刚好可用,那么这个线程可以无需阻塞直接获取到锁,所以非公平锁有可能出现后申请锁的线程先获得锁的场景。

优点

可以减少唤醒线程的开销,整体吞吐效率高,因为线程有几率不阻塞直接获得锁。

缺点

处于等待队列中的线程可能会饿死,或者等很久才会获得锁。

图示

在这里插入图片描述

源码分析

ReentranLock中默认使用非公平锁,也可以通过构造器显式指定公平锁。

公平锁

        /**
         * 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() &&
                    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;
        }
    }

非公平锁

        /**
         * Performs non-fair tryLock.  tryAcquire is implemented in
         * subclasses, but both need nonfair try for trylock method.
         */
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                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;
        }

通过上图中的源代码对比,我们可以明显地看出公平锁和非公平锁的区别就在于公平锁在获取同步状态时多了一个限制条件hasQueuedPredecessors();

    public final boolean hasQueuedPredecessors() {
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

该方法主要做一件事情,就是判断当前线程是否位于同步对列的第一个,如果是则返回true,如果不是,返回false。

总结

综上所述,公平锁就是通过同步队列来实现多个线程按照申请锁的顺序来获取锁。非公平锁在加锁时不考虑排队等待情况,直接获取锁,所以可能出现后申请的线程先获得锁的情况。

最后

以上就是谦让皮带为你收集整理的公平锁与非公平锁什么是公平锁什么是非公平锁源码分析总结的全部内容,希望文章能够帮你解决公平锁与非公平锁什么是公平锁什么是非公平锁源码分析总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部