synchronized与ReentrantLock底层原理与区别2

   在上一节我们说了synchronized关键字和ReentrantLock锁的区别,如果没有看过上一节的同学可以先看一下,synchronized与ReentrantLock底层原理与区别1
这一节将接着阐述,主要讲解ReentrantLock的公平锁和非公平锁的机制.

一.首先说一下公平锁和非公平锁的概念
   公平锁–>排队一个一个来
   非公平锁–>可以插队
   这里需要指明的是非公平锁并不是随机的,随机还是相对而言比较公平的,而非公平锁就是新来的线程可以直接进行插队.
二.公平锁和非公平锁举例和实现
   其实概念还是很容易理解的,但是很多同学还没有真正理解非公平锁的含义.下面给出一个小demo,大家可以先不用看输出结果,先想一下结果会是什么样子

package 线程;

import java.util.concurrent.locks.ReentrantLock;

/**
 * 公平锁和非公平锁
 * @author tim
 *
 */
public class MyReentrantLock3 {
	
	//新建一个非公平锁
	private static ReentrantLock lock=new ReentrantLock(false);
	
	static class Task extends Thread{

		int count=0;
		@Override
		public void run() {
			for(;;) {
				try {
					lock.lock();
					count++;
					Thread.sleep(100);   //模拟业务操作,耗时0.1秒
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally {
					lock.unlock();
				}
			}
		}
		
		
	}
	public static void main(String[] args) {
		//开启5个线程,不断循环去抢锁
		Task[] arr=new Task[5];
		for(int i=0;i<5;i++) {
			Task task = new Task();
			task.start();
			arr[i]=task;
		}
		//总共执行10秒钟,每一次耗时0.1秒,也就是总共最多执行100次
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//查看结果
		for(int i=0;i<5;i++) {
			System.out.println(arr[i].getName()+">>>"+arr[i].count);
		}
		//程序退出
		System.exit(0);
		
		
	}

}

以上程序很简单,开启5个线程,每个线程都不断循环去争抢锁,这把锁是非公平锁,大家可以先不看运行结果,猜一下.

结果如下:
在这里插入图片描述
   是不是感到结果有些意外,这就是非公平锁,线程0并没有排队,而是每次插队去争抢锁,所以线程0一直在运行,而其他线程一次都没有运行.
   要注意的是这个结果并不是确定的,因为具体还要取决于cpu的调度.

   现在将锁改为公平锁,在ReentrantLock的构造函数中从传入true即可,下面贴上运行结果.
在这里插入图片描述
   可以看到,每一个线程都均匀的运行20次,因为每次都需要排队.

三.非公平锁在开发中需要注意的问题
   在真正理解了非公平锁之后,就要注意他可能带来的问题.非公平锁可能带来线程饥饿问题,就是有些线程一直获取不到资源.
   在用户访问请求的时候,都会开启一个线程,比如一瞬间开启了十个线程,需要查询数据库,用到数据库连接池,但是连接池中的连接是有限的,比如说有三个连接,为了保证某个线程在抢到一个连接后不被其他线程再一次抢占,需要加锁,如果是非公平锁,那么就可能发生线程饥饿的事件,带来的结果就是有些用户一直在等待,响应时间激增,系统突然抖动.

要注意大多数情况还是用的非公平锁,因为公平锁会带来性能损耗,少部分需要考虑线程饥饿情况,使用公平锁.

在下一节将会和大家一起手写lock,从底层去更加理解锁的机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员bling

义父,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值