公平锁与非公平锁 - morris131/morris-book GitHub Wiki
公平锁,就是很公平,在并发环境中,每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个,就占有锁,否则就会加入到等待队列中,以后会按照FIFO的规则从队列中取到自己。
非公平锁是不管线程是否是先运行,都是随机获得锁的。
如果在绝对时间上,先对锁进行获取的请求一定先被满足,那么这个锁是公平的,反之,是不公平的。公平的获取锁,也就是等待时间最长的线程最优先获取锁,也可以说锁获取是顺序的。ReentrantLock提供了一个构造函数,能够控制锁是否是公平的。
事实上,公平的锁机制往往没有非公平的效率高,但是,并不是任何场景都是以TPS作为 唯一的指标,公平锁能够减少“饥饿”发生的概率,等待越久的请求越是能够得到优先满足。
package com.morris.ch4;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class FairLockTest {
public static void main(String[] args) {
Service service = new Service(true);
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "is running");
service.method();
}
};
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(runnable);
}
for (int i = 0; i < 10; i++) {
threads[i].start();
}
}
static class Service {
private Lock lock;
Service(boolean isFair) {
lock = new ReentrantLock(isFair);
}
public void method() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "is get lock");
} finally {
lock.unlock();
}
}
}
}
运行结果如下:
Thread-2is running
Thread-1is running
Thread-4is running
Thread-3is running
Thread-0is running
Thread-6is running
Thread-2is get lock
Thread-7is running
Thread-5is running
Thread-8is running
Thread-1is get lock
Thread-9is running
Thread-4is get lock
Thread-3is get lock
Thread-0is get lock
Thread-6is get lock
Thread-7is get lock
Thread-5is get lock
Thread-8is get lock
Thread-9is get lock
package com.morris.ch4;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class FairLockTest {
public static void main(String[] args) {
Service service = new Service(false);
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "is running");
service.method();
}
};
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(runnable);
}
for (int i = 0; i < 10; i++) {
threads[i].start();
}
}
static class Service {
private Lock lock;
Service(boolean isFair) {
lock = new ReentrantLock(isFair);
}
public void method() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "is get lock");
} finally {
lock.unlock();
}
}
}
}
运行结果如下:
Thread-0is running
Thread-5is running
Thread-6is running
Thread-1is running
Thread-8is running
Thread-3is running
Thread-4is running
Thread-2is running
Thread-7is running
Thread-0is get lock
Thread-6is get lock
Thread-9is running
Thread-9is get lock
Thread-5is get lock
Thread-1is get lock
Thread-8is get lock
Thread-3is get lock
Thread-4is get lock
Thread-2is get lock
Thread-7is get lock