公平与非公平锁:锁lock分为 公平锁和非公平锁,公平锁表示现场获取锁的顺序是按照线程加锁的顺序来分配的,
即先来先得的FIFO先进先出顺序。而非公平锁就是一种获取锁的抢占机制,是随机获得的锁的,和公平锁不一样的就是先来
不一定先得到锁,这个方式可能造成某些线程一直拿不到锁。
首先来验证公平锁:创建service方法,使用lock进行锁定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class Service { private ReentrantLock lock; public Service( boolean isFair){ super (); System.out.println(isFair); lock= new ReentrantLock(isFair); } public void serviceMethod(String str){ try { lock.lock(); if ( "a" .equals(str)){ //将启动的线程全部阻塞在此 try { Thread.sleep( 2000 ); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println( "ThreadName= " +Thread.currentThread().getName()+ " 获得了锁" ); } finally { lock.unlock(); } } } |
然后运行验证:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | public class Run { public static void main(String[] args) throws InterruptedException { fair( true ); // fair(false); } public static void fair( boolean isFair) throws InterruptedException{ final Service service= new Service(isFair); new Thread( new Runnable() { public void run() { System.out.println( "第一个线程,起阻塞后面线程作用" ); service.serviceMethod( "a" ); } }).start(); Thread.sleep( 500 ); Runnable runnable= new Runnable() { public void run() { System.out.println( "线程 " +Thread.currentThread().getName()+ " 运行了" ); service.serviceMethod( "b" ); } }; Thread [] threads= new Thread[ 10 ]; for ( int i = 0 ; i < threads.length; i++) { threads[i]= new Thread(runnable); } for ( int i = 0 ; i < threads.length; i++) { threads[i].start(); } } } |
公平锁控制台:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | true 第一个线程,起阻塞后面线程作用 线程 Thread- 1 运行了 线程 Thread- 2 运行了 线程 Thread- 3 运行了 线程 Thread- 4 运行了 线程 Thread- 5 运行了 线程 Thread- 6 运行了 线程 Thread- 7 运行了 线程 Thread- 8 运行了 线程 Thread- 9 运行了 线程 Thread- 10 运行了 ThreadName= Thread- 0 获得了锁 ThreadName= Thread- 1 获得了锁 ThreadName= Thread- 2 获得了锁 ThreadName= Thread- 3 获得了锁 ThreadName= Thread- 4 获得了锁 ThreadName= Thread- 5 获得了锁 ThreadName= Thread- 7 获得了锁 ThreadName= Thread- 6 获得了锁 ThreadName= Thread- 8 获得了锁 ThreadName= Thread- 9 获得了锁 ThreadName= Thread- 10 获得了锁 |
可以发现,控制台是有序的,其中0线程是为了方便观看,特意增加,将所有的线程阻塞在此。
非公平锁的控制台:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | false 第一个线程,起阻塞后面线程作用 线程 Thread- 1 运行了 线程 Thread- 3 运行了 线程 Thread- 2 运行了 线程 Thread- 4 运行了 线程 Thread- 5 运行了 线程 Thread- 10 运行了 线程 Thread- 9 运行了 线程 Thread- 8 运行了 线程 Thread- 7 运行了 线程 Thread- 6 运行了 ThreadName= Thread- 0 获得了锁 ThreadName= Thread- 2 获得了锁 ThreadName= Thread- 3 获得了锁 ThreadName= Thread- 1 获得了锁 ThreadName= Thread- 4 获得了锁 ThreadName= Thread- 5 获得了锁 ThreadName= Thread- 10 获得了锁 ThreadName= Thread- 9 获得了锁 ThreadName= Thread- 8 获得了锁 ThreadName= Thread- 6 获得了锁 ThreadName= Thread- 7 获得了锁 |
可以发现,先进但不是先获得锁,是无序的。ReentranReentrantLock默认是非公平的。
顺便留下几个lock中常用的方法:
lock.getHoldCount(); 查询当前线程保持此锁定的个数。也就是调用lock()方法的次数。
lock.getQueuelength();返回正在等待获取次锁定的线程估计数。例如五个线程,1一个线程正在制定await()方法,name咋动用此方法后返回4.
lock.getWaitQueueLength(Condition,condition); 返回等待与此锁定相关的给定条件Condition的线程估计数。比如有五个线程执行同一个condition对象的await()方法,
调用此方法之后返回5.
每一个优秀的人,都有一段沉默的时光,不抱怨,不诉苦,最后度过那段感动自己的日子。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步