美文网首页
锁 - 公平 vs 非公平

锁 - 公平 vs 非公平

作者: 面向对象架构 | 来源:发表于2022-11-22 00:07 被阅读0次

公平锁 非公平锁

公平锁

典型的公平锁:ReentrantLock(true)

多个线程按照申请锁的顺序来获取锁。

作用:严格按照线程启动的顺序来执行,不允许其他线程插队执行。

优点:等待锁的线程不会饿死。

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

非公平锁

典型的非公平锁:ReentrantLock(false)、synchronized

多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。

对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。
对于Synchronized而言,也是一种非公平锁。由于其并不像ReentrantLock是通过AQS的来实现线程调度,所以并没有任何办法使其变成公平锁。
上来就直接尝试占有锁,如果尝试失败,就再采用类似公平锁那种方式。

作用:线程启动允许插队的。

优点:可以减少唤起线程的开销,吞吐量比公平锁大。,因为线程有几率不阻塞直接获得锁,CPU不必唤醒所有线程。

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

    // 公平锁
    // 在公平锁中,获得锁的方法tryAcquire中多了 !hasQueuedPredecessors()判断。
    protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                // hasQueuedPredecessors 这个方法就是最大区别所在
                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;
        }
    }
 
    // 非公平锁
    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;
        }
    }
从图上就可以清晰看出公平和非公平的区别

比较

1.非公平锁的效率高于公平锁。

2.非公平锁并非真正随机,其获取锁还是有一定顺序的。

3.究竟公平与非公平有何区别呢?

a、若在释放锁的时候总是没有新的兔子来打扰,则非公平锁等于公平锁;

b、若释放锁的时候,正好一个兔子来喝水,而此时位于队列头的兔子还没有被唤醒(因为线程上下文切换是需要不少开销的),此时后来的兔子则优先获得锁,成功打破公平,成为非公平锁;

4.非公平锁的效率为何高于公平锁呢?

上文说到的线程切换的开销,其实就是非公平锁效率高于公平锁的原因,因为非公平锁减少了线程挂起的几率,后来的线程有一定几率逃离被挂起的开销。

相关文章

  • 公平锁和非公平锁-ReentrantLock是如何实现公平、非公

    1、什么是公平锁与非公平锁 公平锁:公平锁就是保障了多线程下各线程获取锁的顺序,先到的线程优先获取锁。非公平锁:非...

  • 公平锁 VS 非公平锁

    公平锁: 线程通过排队的方式来获取锁,没有获取到锁的线程以阻塞的状态等待,吞吐量不如非公平锁,但是线程不会被饿死,...

  • 锁 - 公平 vs 非公平

    公平锁 非公平锁 公平锁 典型的公平锁:ReentrantLock(true) 多个线程按照申请锁的顺序来获取锁。...

  • 聊聊Java中的那些锁

    说到Java中锁的分类,有很多种。本文就来聊聊公平锁、非公平锁、可重入锁、独占锁、共享锁和自旋锁。 一、公平锁和非...

  • 多线程并发编程

    Wait/NotifyAll标准使用 锁的特性/分类 公平、非公平锁 可重入锁 排他、非排他锁 Synchroni...

  • java并发-独占锁与共享锁,公平锁与非公平锁,重入锁与非重入锁

    java并发-乐观锁与悲观锁,独占锁与共享锁,公平锁与非公平锁,重入锁与非重入锁 java 中的锁 -- 偏向锁、...

  • java 锁(五):公平锁VS非公平锁

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

  • [转载]# 公平锁,非公平锁,乐观锁,悲观锁 公平锁/非公平锁(多线程执行顺序的维度) 概念理解 公平锁:加锁前先...

  • AbstractQueuedSynchronizer- 独占锁实

    1-ReentrantLock ReentrantLock是独占锁,而且内部可以是公平锁,非公平锁;公平锁:公平锁...

  • 14、各种锁的理解

    1、公平锁、非公平锁 公平锁:非常公平,不能插队,必须先来后到。 非公平锁:非常不公平,可以插队(synchron...

网友评论

      本文标题:锁 - 公平 vs 非公平

      本文链接:https://www.haomeiwen.com/subject/asasxdtx.html