概述
什么是公平锁,什么是非公平锁?
公平锁是指按照线程的请求顺序去加锁;
非公平锁是指不完全按照线程的请求顺序进行加锁,一定情况下是允许插队的。
线程唤醒的开销比较大,使用非公平锁可以避免线程唤醒带来的空档期而导致资源的浪费。
公平锁与非公平锁代码演示
下面进行公平锁和非公平锁的代码演示,请看下代码
公平锁实例代码
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不遵守排队,可以进行插队。