在Java的ReentrantLock构造函数中提供了两种锁:创建公平锁和非公平锁(默认)。代码如下:
public ReentrantLock() { sync = new NonfairSync(); } public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
此例可反应公平锁和非公平锁的差异:
package concurrency; import java.util.concurrent.locks.ReentrantLock; /** * @author yuanxu * Apr 11, 2017 9:59:24 PM */ public class ReentrantLockTest { private static final ReentrantLock lock = new ReentrantLock(); private static final ReentrantLock fairlock = new ReentrantLock(true); private int n; public static void main(String[] args) { // TODO Auto-generated method stub ReentrantLockTest rlt = new ReentrantLockTest(); for (int i=0; i<100; i++) { Thread nonT = new Thread(new NonFairTestThread(rlt)); nonT.setName("nonFair[" + (i + 1) + "]"); nonT.start(); Thread fairT = new Thread(new FairTestThread(rlt)); fairT.setName("fair[" + (i + 1) + "]"); fairT.start(); } } static class NonFairTestThread implements Runnable { private ReentrantLockTest rlt; public NonFairTestThread(ReentrantLockTest rlt) { this.rlt = rlt; } public void run() { lock.lock(); try { rlt.setNum(rlt.getNum() + 1); System.out.println(Thread.currentThread().getName() + " nonfairlock***************" + rlt.getNum()); } finally { lock.unlock(); } } } static class FairTestThread implements Runnable { private ReentrantLockTest rlt; public FairTestThread(ReentrantLockTest rlt) { this.rlt = rlt; } public void run() { fairlock.lock(); try { rlt.setNum(rlt.getNum() + 1); System.out.println(Thread.currentThread().getName() + " fairlock=======" + rlt.getNum() + " " + fairlock.getHoldCount() + " queuelength=" + fairlock.getQueueLength()); } finally { fairlock.unlock(); } } } public void setNum(int n) { this.n = n; } public int getNum() { return n; } }
运行结果反映:
在公平的锁上,线程按照他们发出请求的顺序获取锁,但在非公平锁上,则允许‘插队’。
在公平的锁中,如果有另一个线程持有锁或者有其他线程在等待队列中等待这个所,那么新发出的请求的线程将被放入到队列中。而非公平锁上,只有当锁被某个线程持有时,新发出请求的线程才会被放入队列中。
非公平锁性能高于公平锁性能的原因: 在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。
参考: