公平锁和非公平锁
多数情况下,锁的申请都是非公平的,例如:线程1首先请求锁A,接着线程2也请求了锁A。那么当锁A可用时,是线程1可获得锁还是线程2可获得锁呢? 这
是一定的,系统只是会从这个锁的等待队列中随机挑选一个,因此不能保证其公平性。这就好比地铁上车,如果不排队,大家都在门口抢上车,结果是
谁先挤进去谁先上车,最终导致的结果是,有些人可能一直无法上车。而公平锁,则不是这样,它会按照到达的先后顺序获得资源。
公平锁的一大特点是:它不会产生饥饿现象,它可以是排队,最终还是可以等到资源的;
synchronized关键字默认是有jvm内部实现控制的,是非公平锁。
ReentrantLock运行开发者自己设置锁的公平性。
示例:
import java.util.concurrent.locks.ReentrantLock;
/**
* 使用ReentrantLock公平锁演示线程同步
*/
public class LockMain {
/**
* 公平锁,保证线程按照请求锁的顺序获取锁
*/
private static ReentrantLock fairLock = new ReentrantLock(true);
/**
* 线程A,用于演示公平锁的使用
*/
public static class A extends Thread {
public A(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
// 尝试获取公平锁
fairLock.lock();
System.out.println(this.getName()+":获取到锁");
// TODO: 在这里执行需要同步的操作
} finally {
// 无论是否成功获取到锁,最终都要释放锁
fairLock.unlock();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
A a1 = new A("a1");
A a2 = new A("a2");
A a3 = new A("a3");
// 确保a1和a2线程执行完毕后再启动a3线程,演示公平锁的特性
a1.start();
a1.join();
a2.start();
a2.join();
a3.start();
a3.join();
}
}