从字面上看,其实很简单。公平意味着每个人都排队买票。不公平是指有人开了超级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大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习