公平锁与非公平锁

概述

  什么是公平锁,什么是非公平锁?

  公平锁是指按照线程的请求顺序去加锁;

  非公平锁是指不完全按照线程的请求顺序进行加锁,一定情况下是允许插队的。

  线程唤醒的开销比较大,使用非公平锁可以避免线程唤醒带来的空档期而导致资源的浪费。

公平锁与非公平锁代码演示

  下面进行公平锁和非公平锁的代码演示,请看下代码

  公平锁实例代码

  

package com.yang.lock;

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 公平锁和非公平锁代码演示
 * cnxieyang@163.com
 */
public class FairLock {
    public static void main(String[] args) {
        PrintQueue printQueue = new PrintQueue();
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(new Job(printQueue));
        }

        for (int i=0;i<10;i++){
            threads[i].start();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Job implements Runnable{
    private PrintQueue printQueue;

    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开始打印");
        printQueue.printDocument(new Object());
        System.out.println(Thread.currentThread().getName()+"打印结束");
    }
}

class PrintQueue {
    //公平锁
    private Lock queueLock = new ReentrantLock(true);

    public void printDocument(Object document) {
        queueLock.lock();
        try {
            int duration =new Random().nextInt(10)+1;
            System.out.println(Thread.currentThread().getName() + "正在执行文件打印操作,需要"+duration);
            Thread.sleep(duration*1000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
        //打印两份
        queueLock.lock();
        try {
            int duration =new Random().nextInt(10)+1;
            System.out.println(Thread.currentThread().getName() + "正在执行文件打印操作,需要"+duration);
            Thread.sleep(duration*1000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
    }
}

 

  执行结果如下所示:

  

Thread-0开始打印
Thread-0正在执行文件打印操作,需要10
Thread-1开始打印
Thread-2开始打印
Thread-3开始打印
Thread-4开始打印
Thread-5开始打印
Thread-6开始打印
Thread-7开始打印
Thread-8开始打印
Thread-9开始打印
Thread-1正在执行文件打印操作,需要9
Thread-2正在执行文件打印操作,需要3
Thread-3正在执行文件打印操作,需要6
Thread-4正在执行文件打印操作,需要2
Thread-5正在执行文件打印操作,需要1
Thread-6正在执行文件打印操作,需要8
Thread-7正在执行文件打印操作,需要1
Thread-8正在执行文件打印操作,需要3
Thread-9正在执行文件打印操作,需要6
Thread-0正在执行文件打印操作,需要10
Thread-0打印结束
Thread-1正在执行文件打印操作,需要2
Thread-1打印结束
Thread-2正在执行文件打印操作,需要9
Thread-2打印结束
Thread-3正在执行文件打印操作,需要5
Thread-3打印结束
Thread-4正在执行文件打印操作,需要8
Thread-4打印结束
Thread-5正在执行文件打印操作,需要4
Thread-5打印结束
Thread-6正在执行文件打印操作,需要5
Thread-6打印结束
Thread-7正在执行文件打印操作,需要1
Thread-7打印结束
Thread-8正在执行文件打印操作,需要3
Thread-8打印结束
Thread-9正在执行文件打印操作,需要9
Thread-9打印结束

Process finished with exit code 0

  

非公平锁实例代码

  

package com.yang.lock;

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 公平锁和非公平锁代码演示
 * cnxieyang@163.com
 */
public class FairLock {
    public static void main(String[] args) {
        PrintQueue printQueue = new PrintQueue();
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(new Job(printQueue));
        }

        for (int i=0;i<10;i++){
            threads[i].start();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Job implements Runnable{
    private PrintQueue printQueue;

    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开始打印");
        printQueue.printDocument(new Object());
        System.out.println(Thread.currentThread().getName()+"打印结束");
    }
}

class PrintQueue {
    //非公平锁
    private Lock queueLock = new ReentrantLock(false);

    public void printDocument(Object document) {
        queueLock.lock();
        try {
            int duration =new Random().nextInt(10)+1;
            System.out.println(Thread.currentThread().getName() + "正在执行文件打印操作,需要"+duration);
            Thread.sleep(duration*1000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
        //打印两份
        queueLock.lock();
        try {
            int duration =new Random().nextInt(10)+1;
            System.out.println(Thread.currentThread().getName() + "正在执行文件打印操作,需要"+duration);
            Thread.sleep(duration*1000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
    }
}

 

  运行结果如下所示:

  

Thread-0开始打印
Thread-0正在执行文件打印操作,需要7
Thread-1开始打印
Thread-2开始打印
Thread-3开始打印
Thread-4开始打印
Thread-5开始打印
Thread-6开始打印
Thread-7开始打印
Thread-8开始打印
Thread-9开始打印
Thread-0正在执行文件打印操作,需要9
Thread-0打印结束
Thread-1正在执行文件打印操作,需要1
Thread-1正在执行文件打印操作,需要5
Thread-1打印结束
Thread-2正在执行文件打印操作,需要8
Thread-2正在执行文件打印操作,需要3
Thread-2打印结束
Thread-3正在执行文件打印操作,需要10
Thread-3正在执行文件打印操作,需要6
Thread-3打印结束
Thread-4正在执行文件打印操作,需要3
Thread-4正在执行文件打印操作,需要4
Thread-4打印结束
Thread-5正在执行文件打印操作,需要1
Thread-5正在执行文件打印操作,需要8
Thread-5打印结束
Thread-6正在执行文件打印操作,需要5
Thread-6正在执行文件打印操作,需要2
Thread-6打印结束
Thread-7正在执行文件打印操作,需要8
Thread-7正在执行文件打印操作,需要4
Thread-7打印结束
Thread-8正在执行文件打印操作,需要6
Thread-8正在执行文件打印操作,需要8
Thread-8打印结束
Thread-9正在执行文件打印操作,需要7
Thread-9正在执行文件打印操作,需要6
Thread-9打印结束

Process finished with exit code 0

  从上数两个代码的运行结果中,我们可以公平锁和非公平锁的差异。

   tryLock不遵守排队,可以进行插队。

posted @ 2020-04-22 20:01  cnxieyang  阅读(349)  评论(0编辑  收藏  举报
联系邮箱:cnxieyang@163.com