Java中的公平锁和非公平锁 - 极悦
首页 课程 师资 教程 报名

Java中的公平锁和非公平锁

  • 2022-08-16 07:39:26
  • 1010次 极悦

从字面上看,其实很简单。公平意味着每个人都排队买票。不公平是指有人开了超级VIP,跳线。所以在多线程中,有公平锁和不公平锁。如何理解?

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

优点:所有线程都可以获得资源,不会在队列中饿死。

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

不公平锁:多个线程不按照申请锁的顺序获取锁,而是直接尝试同时获取锁(插入队列中)。如果获取失败(插入失败),则进入队列等待(如果排队失败),如果可以获取(成功跳转队列),则直接获取锁。

优点:可以减少CPU唤醒线程的开销,整体吞吐效率会更高,而且CPU不必唤醒所有线程,会减少被调用的线程数。

缺点:可能会导致队列中排队的线程无法获取锁或获取锁时间过长,饿死。

在Java多线程并发操作中,我们操作锁大部分时候都是基于Sync本身实现的,但是Sync本身是ReentrantLock本身的一个内部类,而Sync本身继

从字面上看,其实很简单。公平意味着每个人都排队买票。不公平是指有人开了超级VIP,跳线。所以在多线程中,有公平锁和不公平锁。如何理解?

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

优点:所有线程都可以获得资源,不会在队列中饿死。

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

不公平锁:多个线程不按照申请锁的顺序获取锁,而是直接尝试同时获取锁(插入队列中)。如果获取失败(插入失败),则进入队列等待(如果排队失败),如果可以获取(成功跳转队列),则直接获取锁。

优点:可以减少CPU唤醒线程的开销,整体吞吐效率会更高,而且CPU不必唤醒所有线程,会减少被调用的线程数。

缺点:可能会导致队列中排队的线程无法获取锁或获取锁时间过长,饿死。

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

那么我们如何实现公平锁和不公平锁呢?我们以买票为例,通过 ReentrantLock 进行说明:

公共类 FairLocked 实现 Runnable {
	私人 int 座位号 = 100;
	/**
	 * 公平锁实现ReentrantLock在构造方法中设置为true:代表公平锁
	 *
	 * 设置为false:表示不公平锁默认也是不公平锁
	 *
	 */
	/** 私有 ReentrantLock 锁 = new ReentrantLock(true); */
	/** 私有 ReentrantLock 锁 = new ReentrantLock(false); */
	私有 ReentrantLock 锁 = new ReentrantLock();
	@Override
	公共无效运行(){
		而(真){
			尝试 {
				lock.lock();
				如果(座位号> 0){
					线程.sleep(100);
					- 座位号;
					System.out.println(Thread.currentThread().getName() + "占用1个座位,还有一个座位" + seatNumber + "座位");
				} 别的 {
					System.out.println(Thread.currentThread().getName() + ": 不好意思,票卖完了!");
					休息;
				}
			} 捕捉(InterruptedException e){
				e.printStackTrace();
			} 最后 {

				lock.unlock();
			}
		}
	}
	公共静态无效主要(字符串[]参数){
		FairLocked rlbr = new FairLocked();
		线程 t1 = new Thread(rlbr, "A window");
		线程 t2 = new Thread(rlbr, "B window");
		t1.start();
		t2.start();
	}
}

需要注意的是,默认情况下是不公平的。如果你想要一个公平的锁,你必须将它设置为 true。因此,查看上面的输出,可以看到 A 线程和 B 线程之间存在资源争用(跳线)。这是一个不公平的锁。我们设置为true看看效果如何:

可以看出AB线程是非常有序的,也就是排队执行!如果大家想了解更多相关知识,可以关注极悦的Java多线程编程,里面有更丰富的知识等着大家去学习,希望对大家能够有所帮助。

选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交