目录
一、公平锁与非公平锁的理解
- 一、公平锁与非公平锁的理解
- 二、公平锁与非公平锁的优缺点
- 三、公平锁与非公平锁的创建方式
- 三、ReentrantLock类中实现公平锁部分源码
- 四、ReentrantLock类中实现非公平锁部分源码
- 五、公平锁代码示例
- 五、非公平锁代码示例
- 公平锁:表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序
- 非公平锁:一种获取锁的抢占机制,是随机获得锁的,和公平锁不一样的就是先来的不一定先得到锁,这个方式可能造成某些线程一直拿不到锁,结果也就是不公平的了。
1、公平锁
- 优点:所有的线程都能得到资源,不会饿死在队列中。
- 缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大。
2、非公平锁
- 优点:可以减少CPU唤醒线程的开销,整体的吞吐效率会高点,CPU也不必取唤醒所有线程,会减少唤起线程的数量。
- 缺点:可能导致队列中间的线程一直获取不到锁或者长时间获取不到锁,导致饿死。
-
创建一个非公平锁(默认是非公平锁)
//创建非公平锁方式一 Lock lock = new ReentrantLock(); //创建非公平锁方式二 Lock lock = new ReentrantLock(false);
-
创建一个公平锁
//创建公平锁,构造传参true Lock lock = new ReentrantLock(true);
-
源码截图
1、FairSync 公平锁源码
/**
* 公平锁的同步对象
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc 0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count --;
System.out.println(Thread.currentThread().getName() + "卖票成功,余票为:" + count);
}
reentrantLock.unlock();
}
}
public static void main(String[] args) {
Demo2 d=new Demo2();
//第1个线程
new Thread(new Runnable() {
@Override
public void run() {
d.getCount();
}
}).start();
//第2个线程
new Thread(new Runnable() {
@Override
public void run() {
d.getCount();
}
}).start();
//第3个线程
new Thread(new Runnable() {
@Override
public void run() {
d.getCount();
}
}).start();
}
}
2、输出结果
1、代码
package com.xz.thread.t10;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @description: 非公平锁示例代码
* @author: xz
*/
public class Demo {
//总票数
private int count =10;
//创建锁 ReentrantLock可实现公平锁与非公平锁
private Lock reentrantLock = new ReentrantLock();
//获取余票数量方法
public void getCount(){
while (true){
//锁住
reentrantLock.lock();
if (count > 0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count --;
System.out.println(Thread.currentThread().getName() + "卖票成功,余票为:" + count);
}
reentrantLock.unlock();
}
}
public static void main(String[] args) {
Demo d=new Demo();
//第1个线程
new Thread(new Runnable() {
@Override
public void run() {
d.getCount();
}
}).start();
//第2个线程
new Thread(new Runnable() {
@Override
public void run() {
d.getCount();
}
}).start();
//第3个线程
new Thread(new Runnable() {
@Override
public void run() {
d.getCount();
}
}).start();
}
}
2、输出结果