记录二:公平锁和非公平锁

编程入门 行业动态 更新时间:2024-10-25 08:19:05

记录二:<a href=https://www.elefans.com/category/jswz/34/1754813.html style=公平锁和非公平锁"/>

记录二:公平锁和非公平锁

目录

公平锁和非公平锁概念

案例演示

为何默认非公平锁

应用场景


公平锁和非公平锁的概念

公平锁:是指多个线程按照申请锁的顺序来获取锁,这里类似排队买票,先来的人先买后来的人在队尾排着,这是公平的。如:

Lock lock = new Reentrant(true); //ture表示公平锁,先来先得。

非公平锁:是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁,在高并发环境下,有可能造成优先级翻转或者饥饿的状态(某一个线程一直得不到锁)。如:

Lock lock = new ReentrantLock(false); //false 表示非公平锁,后来的也可能先获得锁
Lock lock = new ReentrantLock();//默认非公平锁

案例演示


import java.util.concurrent.locks.ReentrantLock;class Ticket {//资源类,模拟三个售票员买完30张票private int number = 30;ReentrantLock lock = new ReentrantLock(true);//true 公平锁 ,默认false 非公平锁public void sale() {lock.lock();try {if(number > 0){System.out.println(Thread.currentThread().getName()+ "卖出第:\t" + number-- +"\t 还剩下:" + number);}} finally {lock.unlock();}}
}public class LockTest {public static void main(String[] args) {Ticket ticket = new Ticket();new Thread(() -> {for (int i = 0; i < 55; i++) {ticket.sale();}}, "t1").start();new Thread(() -> {for (int i = 0; i < 55; i++) {ticket.sale();}}, "t2").start();new Thread(() -> {for (int i = 0; i < 55; i++) {ticket.sale();}}, "t3").start();}
}

公平锁结果集:

t1卖出第:	30	 还剩下:29
t2卖出第:	29	 还剩下:28
t1卖出第:	28	 还剩下:27
t2卖出第:	27	 还剩下:26
t1卖出第:	26	 还剩下:25
t3卖出第:	25	 还剩下:24
t2卖出第:	24	 还剩下:23
t1卖出第:	23	 还剩下:22
t3卖出第:	22	 还剩下:21
t2卖出第:	21	 还剩下:20
t1卖出第:	20	 还剩下:19
t3卖出第:	19	 还剩下:18
t2卖出第:	18	 还剩下:17
t1卖出第:	17	 还剩下:16
t3卖出第:	16	 还剩下:15
t2卖出第:	15	 还剩下:14
t1卖出第:	14	 还剩下:13
t3卖出第:	13	 还剩下:12
t2卖出第:	12	 还剩下:11
t1卖出第:	11	 还剩下:10
t3卖出第:	10	 还剩下:9
t2卖出第:	9	 还剩下:8
t1卖出第:	8	 还剩下:7
t3卖出第:	7	 还剩下:6
t2卖出第:	6	 还剩下:5
t1卖出第:	5	 还剩下:4
t3卖出第:	4	 还剩下:3
t2卖出第:	3	 还剩下:2
t1卖出第:	2	 还剩下:1
t3卖出第:	1	 还剩下:0Process finished with exit code 0

非公平锁结果集:

t3卖出第:	30	 还剩下:29
t3卖出第:	29	 还剩下:28
t3卖出第:	28	 还剩下:27
t3卖出第:	27	 还剩下:26
t3卖出第:	26	 还剩下:25
t3卖出第:	25	 还剩下:24
t3卖出第:	24	 还剩下:23
t3卖出第:	23	 还剩下:22
t3卖出第:	22	 还剩下:21
t3卖出第:	21	 还剩下:20
t3卖出第:	20	 还剩下:19
t3卖出第:	19	 还剩下:18
t3卖出第:	18	 还剩下:17
t3卖出第:	17	 还剩下:16
t1卖出第:	16	 还剩下:15
t1卖出第:	15	 还剩下:14
t1卖出第:	14	 还剩下:13
t1卖出第:	13	 还剩下:12
t1卖出第:	12	 还剩下:11
t1卖出第:	11	 还剩下:10
t1卖出第:	10	 还剩下:9
t1卖出第:	9	 还剩下:8
t1卖出第:	8	 还剩下:7
t1卖出第:	7	 还剩下:6
t1卖出第:	6	 还剩下:5
t1卖出第:	5	 还剩下:4
t1卖出第:	4	 还剩下:3
t1卖出第:	3	 还剩下:2
t1卖出第:	2	 还剩下:1
t1卖出第:	1	 还剩下:0Process finished with exit code 0

结论:可以看到公平锁3个线程相对都可以获取到资源,非公平锁只有2个线程有获取到资源,也可能有1个或者3个线程都能获取到资源。

为何默认非公平锁

1.恢复挂起的线程到获取到真正的锁还是有时间差的,从开发人员看这个时间微乎其微,但是从CPU的角度来看,这个时间差存在的还是很明显的。所以非公平锁能更充分的利用CPU的时间片,尽量减少CPU空闲状态时间。

2.使用多线程很重要的考量点线程切换的开销,当采用非公平锁时,当1个线程请求锁获取同步状态,然后释放同步状态,那么刚释放锁的线程在此刻再次获取同步状态的概率就变得非常大,所以就减少了线程的开销。

应用场景

非公平锁:如果系统为了获得更高的吞吐量,很显然非公平锁是比较合适的,因为节省很多线程切换时间的,吞吐量自然就上去了;

公平锁:承上 否则那就用公平锁,大家公平使用

另外思考下

1.synchronized 是公平锁还是非公平锁呢?案例说明是非公平锁

 class SaleShop {//获取食物public void goShop() {System.out.println(Thread.currentThread().getName()+":排队中");synchronized (this) {System.out.println(Thread.currentThread().getName()+":买东西");}}
}
public class SyncLockTest {public static void main(String[] args) {SaleShop saleShop = new SaleShop();//让5个人去购买东东for (int i=0; i<5; i++) {new Thread(saleShop::goShop,"编号:"+(i+1)).start();}}
}

某一次结果:

编号:1:排队中
编号:3:排队中
编号:2:排队中
编号:1:买东西
编号:2:买东西
编号:3:买东西
编号:4:排队中
编号:4:买东西
编号:5:排队中
编号:5:买东西Process finished with exit code 0

总结:排队顺序:1,3,2,4,5 买东西顺序:1,2,3,4,5。第三个人是不是插队了

2.ReentrantLock是如何实现实现公平锁和非公平锁的呢?是基于AbstractQueuedSynchronizer(抽象队列同步器,简称AQS)什么是AQS,下一篇我们继续聊

更多推荐

记录二:公平锁和非公平锁

本文发布于:2024-03-08 22:11:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1722596.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:公平

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!