美文网首页互联网科技程序员Java 杂谈
Java多线程 -- 公平锁和非公平锁

Java多线程 -- 公平锁和非公平锁

作者: cb9841112785 | 来源:发表于2018-06-19 16:59 被阅读285次

在java的锁机制中,公平和非公平的参考物是什么,个人而言觉得是相对产生的结果而立,简单的来说,如果一个线程组里,能保证每个线程都能拿到锁,那么这个锁就是公平锁。相反,如果保证不了每个线程都能拿到锁,也就是存在有线程饿死,那么这个锁就是非公平锁。本文围绕ReenTrantLock来讲。

实现原理

那如何能保证每个线程都能拿到锁呢,队列FIFO是一个完美的解决方案,也就是先进先出,java的ReenTrantLock也就是用队列实现的公平锁和非公平锁。

在公平的锁中,如果有另一个线程持有锁或者有其他线程在等待队列中等待这个所,那么新发出的请求的线程将被放入到队列中。而非公平锁上,只有当锁被某个线程持有时,新发出请求的线程才会被放入队列中(此时和公平锁是一样的)。所以,它们的差别在于非公平锁会有更多的机会去抢占锁。

公平锁:

final Thread current = Thread.currentThread();

            int c = getState();

            if (c == 0) {

                if (!hasQueuedPredecessors() &&

                    compareAndSetState(0, acquires)) {

                    setExclusiveOwnerThread(current);

                    return true;

                }

            }

    #hasQueuedPredecessors的实现

    public final boolean hasQueuedPredecessors() {

        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());

    }

非公平锁:

final Thread current = Thread.currentThread();

            int c = getState();

            if (c == 0) {

                if (compareAndSetState(0, acquires)) {

                    setExclusiveOwnerThread(current);

                    return true;

                }

            }

示例

公平锁:

/**

* Created by Fant.J.

*/

public class MyFairLock {

    /**

    *    true 表示 ReentrantLock 的公平锁

    */

    private  ReentrantLock lock = new ReentrantLock(true);

    public  void testFail(){

        try {

            lock.lock();

            System.out.println(Thread.currentThread().getName() +"获得了锁");

        }finally {

            lock.unlock();

        }

    }

    public static void main(String[] args) {

        MyFairLock fairLock = new MyFairLock();

        Runnable runnable = () -> {

            System.out.println(Thread.currentThread().getName()+"启动");

            nonfairLock.testFail();

        };

        Thread[] threadArray = new Thread[10];

        for (int i=0; i<10; i++) {

            threadArray[i] = new Thread(runnable);

        }

        for (int i=0; i<10; i++) {

            threadArray[i].start();

        }

    }

}

Thread-0启动

Thread-0获得了锁

Thread-1启动

Thread-1获得了锁

Thread-2启动

Thread-2获得了锁

Thread-3启动

Thread-3获得了锁

Thread-4启动

Thread-4获得了锁

Thread-5启动

Thread-5获得了锁

Thread-6启动

Thread-6获得了锁

Thread-8启动

Thread-8获得了锁

Thread-7启动

Thread-7获得了锁

Thread-9启动

Thread-9获得了锁

可以看到,获取锁的线程顺序正是线程启动的顺序。

非公平锁:

/**

* Created by Fant.J.

*/

public class MyNonfairLock {

    /**

    *    false 表示 ReentrantLock 的非公平锁

    */

    private  ReentrantLock lock = new ReentrantLock(false);

    public  void testFail(){

        try {

            lock.lock();

            System.out.println(Thread.currentThread().getName() +"获得了锁");

        }finally {

            lock.unlock();

        }

    }

    public static void main(String[] args) {

        MyNonfairLock nonfairLock = new MyNonfairLock();

        Runnable runnable = () -> {

            System.out.println(Thread.currentThread().getName()+"启动");

            nonfairLock.testFail();

        };

        Thread[] threadArray = new Thread[10];

        for (int i=0; i<10; i++) {

            threadArray[i] = new Thread(runnable);

        }

        for (int i=0; i<10; i++) {

            threadArray[i].start();

        }

    }

}

Thread-1启动

Thread-0启动

Thread-0获得了锁

Thread-1获得了锁

Thread-8启动

Thread-8获得了锁

Thread-3启动

Thread-3获得了锁

Thread-4启动

Thread-4获得了锁

Thread-5启动

Thread-2启动

Thread-9启动

Thread-5获得了锁

Thread-2获得了锁

Thread-9获得了锁

Thread-6启动

Thread-7启动

Thread-6获得了锁

Thread-7获得了锁

可以看出非公平锁对锁的获取是乱序的,即有一个抢占锁的过程。

最后

那非公平锁和公平锁适合什么场合使用呢,他们的优缺点又是什么呢?

优缺点:

非公平锁性能高于公平锁性能。首先,在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。而且,非公平锁能更充分的利用cpu的时间片,尽量的减少cpu空闲的状态时间。

使用场景

使用场景的话呢,其实还是和他们的属性一一相关,举个栗子:如果业务中线程占用(处理)时间要远长于线程等待,那用非公平锁其实效率并不明显,但是用公平锁会给业务增强很多的可控制性。

相关文章

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

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

  • 聊聊Java中的那些锁

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

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

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

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

  • java中各种锁结合源码深度解析

    java中各种锁介绍 1.公平锁 / 非公平锁 公平锁 在java代码中类名是FairSync。 公平锁是指多个线...

  • Java多线程——公平锁和非公平锁

    在java的锁机制中,公平和非公平的参考物是什么,个人而言觉得是相对产生的结果而立,简单的来说,如果一个线程组里,...

  • Java多线程 -- 公平锁和非公平锁

    在java的锁机制中,公平和非公平的参考物是什么,个人而言觉得是相对产生的结果而立,简单的来说,如果一个线程组里,...

  • 常见锁分类

    *Java中的锁分类 公平锁/非公平锁公平锁是指多个线程按照申请锁的顺序来获取锁。非公平锁的优点在于吞吐量比公平锁...

  • java线程锁概念

    java虚拟机分为隐藏锁,显示锁其中隐藏说只可以出力公平锁, 显示锁可以出力公平锁和非公平锁 显示锁可以细分为很...

  • Java中的锁

    Java中的锁 参考了这篇:Java中的锁分类 公平锁/非公平锁(ReentrantLock/Synchroniz...

网友评论

    本文标题:Java多线程 -- 公平锁和非公平锁

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