如何理解Java中的公平锁和非公平锁?

从字面意思理解,其实灰常简单,公平就是大家买票都排队,不公平就是有人开了超级VIP,插队了。所以在多线程中,就存在公平锁和非公平锁,如何理解呢?

公平锁:多个线程按照申请锁的顺序去获得锁,所有线程都在队列里排队,这样就保证了队列中的第一个先得到锁。

优点:所有的线程都能得到资源,不会饿死在队列中。

缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大。

非公平锁:多个线程不按照申请锁的顺序去获得锁,而是同时直接去尝试获取锁(插队),获取不到(插队失败),再进入队列等待(失败则乖乖排队),如果能获取到(插队成功),就直接获取到锁。

优点:可以减少CPU唤醒线程的开销,整体的吞吐效率会高点,CPU也不必取唤醒所有线程,会减少唤起线程的数量。

缺点:可能导致队列中排队的线程一直获取不到锁或者长时间获取不到锁,活活饿死。

在Java多线程并发操作中,我们操作锁大多时候都是基于Sync本身去实现的,而Sync本身却是ReentrantLock本身的一个内部类,Sync本身又继承AbstractQueuedSynchronizer,如图:

那我们如何去实现一个公平锁和非公平锁呢?我们就以买票这个例子,通过ReentrantLock进行讲解:

public class FairLocked implements Runnable {
	private int seatNumber = 100;
	/**
	 * 公平锁实现 ReentrantLock构造方法中设置为true:代表公平锁
	 * 
	 * 设置为false:代表非公平锁 默认也是非公平锁
	 * 
	 */
	/** private ReentrantLock lock = new ReentrantLock(true); */

	/** private ReentrantLock lock = new ReentrantLock(false); */
	private ReentrantLock lock = new ReentrantLock();

	@Override
	public void run() {
		while (true) {
			try {
				lock.lock();
				if (seatNumber > 0) {
					Thread.sleep(100);
					--seatNumber;
					System.out.println(Thread.currentThread().getName() + "占用1个座位,还剩余 " + seatNumber + "个座位");
				} else {
					System.out.println(Thread.currentThread().getName() + ":不好意思,票卖完了!");
					break;
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {

				lock.unlock();
			}
		}
	}

	public static void main(String[] args) {
		FairLocked rlbr = new FairLocked();
		Thread t1 = new Thread(rlbr, "A窗口");
		Thread t2 = new Thread(rlbr, "B窗口");
		t1.start();
		t2.start();
	}
}

需要注意的是,默认情况下是非公平,想要公平锁就得设置为true,所以看上述的输出就可以看出,A线程和B线程存在资源争抢(插队),这个就是非公平锁,我们设置为true看看是什么效果:

可以看出,AB线程是非常有序的,就是进行排队执行!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值