多线程学习 公平锁和非公平锁

公平与非公平锁:锁lock分为 公平锁和非公平锁,公平锁表示现场获取锁的顺序是按照线程加锁的顺序来分配的,

即先来先得的FIFO先进先出顺序。而非公平锁就是一种获取锁的抢占机制,是随机获得的锁的,和公平锁不一样的就是先来

不一定先得到锁,这个方式可能造成某些线程一直拿不到锁。

  

  首先来验证公平锁:创建service方法,使用lock进行锁定。

  

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();
		}
	}
}

  然后运行验证:

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();
		}

	}
}

  公平锁控制台:

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线程是为了方便观看,特意增加,将所有的线程阻塞在此。

非公平锁的控制台:

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.  

  

  每一个优秀的人,都有一段沉默的时光,不抱怨,不诉苦,最后度过那段感动自己的日子。

原文地址:https://www.cnblogs.com/hrlizhi/p/9496411.html

时间: 2024-11-10 01:38:49

多线程学习 公平锁和非公平锁的相关文章

“全栈2019”Java多线程第二十八章:公平锁与非公平锁详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第二十八章:公平锁与非公平锁详解 下一章 "全栈2019"Java多线程第二十九章:可重入锁与不可重入锁详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"J

java多线程20 : ReentrantLock中的方法 ,公平锁和非公平锁

公平锁与非公平锁 ReentrantLock有一个很大的特点,就是可以指定锁是公平锁还是非公平锁,公平锁表示线程获取锁的顺序是按照线程排队的顺序来分配的,而非公平锁就是一种获取锁的抢占机制,是随机获得锁的,先来的未必就一定能先得到锁,从这个角度讲,synchronized其实就是一种非公平锁.非公平锁的方式可能造成某些线程一直拿不到锁,自然是非公平的了.看一下例子,new ReentrantLock的时候有一个单一参数的构造函数表示构造的是一个公平锁还是非公平锁,传入true就可以了: publ

Java多线程编程4--Lock的使用--公平锁和非公平锁

公平与非公平锁:锁Lock分为"公平锁"和"非公平锁",公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序.而非公平锁就是一种获取锁的抢占机制,是随机获得锁的,和公平锁不一样的就是先来的不一定先得到锁,这个方式可能造成某些线程一直拿不到锁,结果也就是不公平的了. 1.公平锁实例 public class Service { private ReentrantLock lock ; public Service(boolean i

公平锁,非公平锁,乐观锁,悲观锁

公平锁/非公平锁(多线程执行顺序的维度) 概念理解 公平锁:加锁前先查看是否有排队等待的线程,有的话优先处理排在前面的线程,先来先得. 非公平所:线程加锁时直接尝试获取锁,获取不到就自动到队尾等待. 例子 ReentrantLock 同时支持两种锁 //创建一个非公平锁,默认是非公平锁 Lock nonFairLock= new ReentrantLock(); Lock nonFairLock= new ReentrantLock(false); //创建一个公平锁,构造传参true Lock

Java中的公平锁和非公平锁实现详解

在ReentrantLock中包含了公平锁和非公平锁两种锁,通过查看源码可以看到这两种锁都是继承自Sync,而Sync又继承自AbstractQueuedSynchronizer,而AbstractQueuedSynchronizer又继承自AbstractOwnableSynchronizer,下面是类的继承关系图: 其中AbstractOwnableSynchronizer是提供了设置占用当前锁的线程信息的方法,主要的锁的实现还是在AbstractQueuedSynchronizer中实现的

理解ReentrantLock的公平锁和非公平锁

学习AQS的时候,了解到AQS依赖于内部的FIFO同步队列来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成一个Node对象并将其加入到同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态. 这时,我有了一个疑问,AQS的同步队列是FIFO的,就是先来排队的先走.那怎么实现非公平锁呢?查阅了一些资料,总算知道了. 首先从公平锁开始看起. ReentrantLock 的公平锁 ReentrantLock 默认采用

synchronized与lock 对象锁、互斥锁、共享锁以及公平锁和非公平锁

synchronized与lock  都是用来实现线程同步的锁,synchronized对象锁,lock是一个接口,她的实现有reentrantlock互斥锁以及ReentrantReadWriteLock共享锁. 这里说明一下ReentrantReadWriteLock共享锁,所谓共享就是该锁提供读读锁共享,即可以多个线程共享一个读取锁,但是读写锁以及读读锁是互斥的. 看到网上有好多介绍介绍锁的种类的,有对象锁.互斥锁.共享锁以及公平锁和非公平锁,但是说明都不够详细了然,在这里用直白的说法记录

公平锁与非公平锁

在Java的ReentrantLock构造函数中提供了两种锁:创建公平锁和非公平锁(默认).代码如下: public ReentrantLock(){ sync = new NonfairSync(); } public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } 在公平的锁上,线程按照他们发出请求的顺序获取锁,但在非公平锁上,则允许'插队':当一个线程请求非公平锁时,如果在发

公平锁与非公平锁源码对比

语义: 1.公平锁:每个线程在获取锁的时候,会先检查该锁维护的等待队列,如果该队列是空或者当前线程是第一个,则占有锁,否则按照FIFO的原则,进入等待队列,等待获取锁: 2.非公平锁:当前线程在获取锁的时候,不管该锁的维护队列种是否有其它等待线程,直接CAS,如果cas失败,则再执行公平锁的那一套: 源码比较如下:公平锁: final void lock() { acquire(1); } 非公平锁: final void lock() { if (compareAndSetState(0, 1