公平锁和非公平锁

如果一个线程组里,能保证每个线程都能拿到锁,那么这个锁就是公平锁。相反,如果保证不了每个线程都能拿到锁,也就是存在有线程饿死,那么这个锁就是非公平锁

公平锁内部维护了一个FIFO队列,按照先入先出的顺序获得锁,而非公平锁存在抢占锁的现象

在公平的锁中,如果有另一个线程持有锁或者有其他线程在等待队列中等待这个锁,那么新发出的请求的线程将被放入到队列中。而非公平锁上,只有当锁被某个线程持有时,新发出请求的线程才会被放入队列中(此时和公平锁是一样的)。所以,它们的差别在于非公平锁会有更多的机会去抢占锁。非公平锁有可能会出现某些线程一直得不到执行,从而饿死的情况。

非公平锁能够尽量利用CPU空闲的时间片段,提高程序执行效率,当一个业务中,执行业务的时间远大于线程等待的时间,那么使用非公平锁的性能并不是很明显,这时候应该用公平锁能够增强对程序的可控性

创建JAVA项目Fair_noFair_test,创建MyService.java类,代码如下:

package test;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyService{
	public Lock lock;
	public  MyService(boolean fair){
	lock = new ReentrantLock(fair);
}

public void testMethod(){
	try{
	lock.lock();
	System.out.println("testMethod "+Thread.currentThread().getName());
	Thread.sleep(500);
	lock.unlock();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}

创建线程类代码如下:

package test;

public class MyThread extends Thread{
	private MyService service;
    public MyThread(MyService service){
			super();
			this.service = service;

}

public void run(){
	service.testMethod();
}

}



创建公平锁测试的运行类Test_1.java代码如下:

package test;
public class Test1_1{
	public static void main(String[] args) throws InterruptedException{
		MyService service = new MyService(true);
		MyThread[] array1 = new MyThread[10];
		MyThread[] array2 =  new MyThread[10];
		for(int i=0; i<array1.length;i++){
			array1[i] = new MyThread(service);
			array1[i].setName("array1+++" + (i+1));
}

for(int i=0;i<array1.length;i++){
array1[i].start();
}

	for(int i=0; i<array2.length;i++){
			array2[i] = new MyThread(service);
			array2[i].setName("array1---" + (i+1));
}

Thread.sleep(500);

for(int i=0;i<array2.length;i++){
array2[i].start();
}

}


}

程序运行结果是+++之前,—在后,说明—没有任何机会抢到锁,这就是公平锁的特点。

创建非公平锁测试的非运行类Test1_2.java代码如下

package test;
public class Test1_1{
	public static void main(String[] args) throws InterruptedException{
		MyService service = new MyService(false);
		MyThread[] array1 = new MyThread[10];
		MyThread[] array2 =  new MyThread[10];
		for(int i=0; i<array1.length;i++){
			array1[i] = new MyThread(service);
			array1[i].setName("array1+++" + (i+1));
}

for(int i=0;i<array1.length;i++){
array1[i].start();
}

	for(int i=0; i<array2.length;i++){
			array2[i] = new MyThread(service);
			array2[i].setName("array1---" + (i+1));
}

Thread.sleep(500);

for(int i=0;i<array2.length;i++){
array2[i].start();
}

}


}

程序运行结果如下
在这里插入图片描述
程序多次运行后,使用非公平锁有可能在第二次输出—,说明后启动的线程先抢占到了锁,这就是非公平锁的特点。
A线程持有锁后,B线程不能执行的原理是在内部执行了unsafe.park(false,0L)代码;A线程释放锁后B线程可以运行的原理是当A线程执行unlock()方法时在内部执行了unsafe.unpark(bThread),B线程得以继续运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值