公平锁与非公平锁
2016-03-24 14:08
211 查看
总括:
在Java的ReentrantLock构造函数中提供了两种锁:创建公平锁和非公平锁(默认)。代码如下:
public ReentrantLock() {
sync = new NonfairSync();
}
在公平的锁上,线程按照他们发出请求的顺序获取锁,但在非公平锁上,则允许‘插队’:当一个线程请求非公平锁时,如果在发出请求的同时该锁变成可用状态,那么这个线程会跳过队列中所有的等待线程而获得锁。 非公平的ReentrantLock 并不提倡 插队行为,但是无法防止某个线程在合适的时候进行插队。
在公平的锁中,如果有另一个线程持有锁或者有其他线程在等待队列中等待这个所,那么新发出的请求的线程将被放入到队列中。而非公平锁上,只有当锁被某个线程持有时,新发出请求的线程才会被放入队列中。
非公平锁性能高于公平锁性能的原因:
在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。
假设线程A持有一个锁,并且线程B请求这个锁。由于锁被A持有,因此B将被挂起。当A释放锁时,B将被唤醒,因此B会再次尝试获取这个锁。与此同时,如果线程C也请求这个锁,那么C很可能会在B被完全唤醒之前获得、使用以及释放这个锁。这样就是一种双赢的局面:B获得锁的时刻并没有推迟,C更早的获得了锁,并且吞吐量也提高了。
当持有锁的时间相对较长或者请求锁的平均时间间隔较长,应该使用公平锁。在这些情况下,插队带来的吞吐量提升(当锁处于可用状态时,线程却还处于被唤醒的过程中)可能不会出现。
公平与非公平锁:锁Lock分为“公平锁”和“非公平锁”,公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序。而非公平锁就是一种获取锁的抢占机制,是随机获得锁的,和公平锁不一样的就是先来的不一定先得到锁,这个方式可能造成某些线程一直拿不到锁,结果也就是不公平的了。
1、公平锁实例
[java] view
plain copy
public class Service {
private ReentrantLock lock ;
public Service(boolean isFair) {
lock = new ReentrantLock(isFair);
}
public void serviceMethod() {
try {
lock.lock();
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ " 获得锁定");
} finally {
lock.unlock();
}
}
}
[java] view
plain copy
public class Run {
public static void main(String[] args) throws InterruptedException {
final Service service = new Service(true); //改为false就为非公平锁了
Runnable runnable = new Runnable() {
public void run() {
System.out.println("**线程: " + Thread.currentThread().getName()
+ " 运行了 " );
service.serviceMethod();
}
};
Thread[] threadArray = new Thread[10];
for (int i=0; i<10; i++) {
threadArray[i] = new Thread(runnable);
}
for (int i=0; i<10; i++) {
threadArray[i].start();
}
}
}
打印的结果是按照线程加锁的顺序输出的,即线程运行了,则会先获得锁
--------------------------------------------------------------------------
把Run类里的true改为false就为非公平锁了
是乱序的,说明先start()启动的线程不代表先获得锁
在Java的ReentrantLock构造函数中提供了两种锁:创建公平锁和非公平锁(默认)。代码如下:
public ReentrantLock() {
sync = new NonfairSync();
}
在公平的锁上,线程按照他们发出请求的顺序获取锁,但在非公平锁上,则允许‘插队’:当一个线程请求非公平锁时,如果在发出请求的同时该锁变成可用状态,那么这个线程会跳过队列中所有的等待线程而获得锁。 非公平的ReentrantLock 并不提倡 插队行为,但是无法防止某个线程在合适的时候进行插队。
在公平的锁中,如果有另一个线程持有锁或者有其他线程在等待队列中等待这个所,那么新发出的请求的线程将被放入到队列中。而非公平锁上,只有当锁被某个线程持有时,新发出请求的线程才会被放入队列中。
非公平锁性能高于公平锁性能的原因:
在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。
假设线程A持有一个锁,并且线程B请求这个锁。由于锁被A持有,因此B将被挂起。当A释放锁时,B将被唤醒,因此B会再次尝试获取这个锁。与此同时,如果线程C也请求这个锁,那么C很可能会在B被完全唤醒之前获得、使用以及释放这个锁。这样就是一种双赢的局面:B获得锁的时刻并没有推迟,C更早的获得了锁,并且吞吐量也提高了。
当持有锁的时间相对较长或者请求锁的平均时间间隔较长,应该使用公平锁。在这些情况下,插队带来的吞吐量提升(当锁处于可用状态时,线程却还处于被唤醒的过程中)可能不会出现。
公平与非公平锁:锁Lock分为“公平锁”和“非公平锁”,公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序。而非公平锁就是一种获取锁的抢占机制,是随机获得锁的,和公平锁不一样的就是先来的不一定先得到锁,这个方式可能造成某些线程一直拿不到锁,结果也就是不公平的了。
1、公平锁实例
[java] view
plain copy
public class Service {
private ReentrantLock lock ;
public Service(boolean isFair) {
lock = new ReentrantLock(isFair);
}
public void serviceMethod() {
try {
lock.lock();
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ " 获得锁定");
} finally {
lock.unlock();
}
}
}
[java] view
plain copy
public class Run {
public static void main(String[] args) throws InterruptedException {
final Service service = new Service(true); //改为false就为非公平锁了
Runnable runnable = new Runnable() {
public void run() {
System.out.println("**线程: " + Thread.currentThread().getName()
+ " 运行了 " );
service.serviceMethod();
}
};
Thread[] threadArray = new Thread[10];
for (int i=0; i<10; i++) {
threadArray[i] = new Thread(runnable);
}
for (int i=0; i<10; i++) {
threadArray[i].start();
}
}
}
**线程: Thread-0 运行了 ThreadName=Thread-0 获得锁定 **线程: Thread-1 运行了 ThreadName=Thread-1 获得锁定 **线程: Thread-4 运行了 **线程: Thread-5 运行了 ThreadName=Thread-4 获得锁定 **线程: Thread-3 运行了 **线程: Thread-7 运行了 **线程: Thread-9 运行了 ThreadName=Thread-5 获得锁定 ThreadName=Thread-3 获得锁定 **线程: Thread-2 运行了 ThreadName=Thread-7 获得锁定 ThreadName=Thread-9 获得锁定 ThreadName=Thread-2 获得锁定 **线程: Thread-6 运行了 ThreadName=Thread-6 获得锁定 **线程: Thread-8 运行了 ThreadName=Thread-8 获得锁定 |
--------------------------------------------------------------------------
把Run类里的true改为false就为非公平锁了
**线程: Thread-1 运行了 **线程: Thread-4 运行了 ThreadName=Thread-1 获得锁定 **线程: Thread-3 运行了 ThreadName=Thread-4 获得锁定 **线程: Thread-6 运行了 **线程: Thread-5 运行了 **线程: Thread-2 运行了 **线程: Thread-0 运行了 ThreadName=Thread-6 获得锁定 **线程: Thread-7 运行了 ThreadName=Thread-7 获得锁定 **线程: Thread-8 运行了 ThreadName=Thread-8 获得锁定 ThreadName=Thread-3 获得锁定 **线程: Thread-9 运行了 ThreadName=Thread-9 获得锁定 ThreadName=Thread-5 获得锁定 ThreadName=Thread-2 获得锁定 ThreadName=Thread-0 获得锁定 |
相关文章推荐
- Yum 查看某个软件的依赖关系
- 王学岗ListView和源码解析(一)
- 第二章:在HTML文档中放置CSS的几种方式
- (4.1.36.6)android Graphics(四):canvas变换与操作
- Windows下的回车换行转换Linux系统下的回车换行
- android应用开发框架+即时通讯IM app开发(1)-前言和工程目录结构
- 来往网页版扫码自动登录的实现原理(微信也是一样)
- android编译源码5.1.1刷真机nexus5系统
- iOS NSNotificationCenter详解
- spring 最全MAVEN 依赖引入配置
- 又一道简单题&&Ladygod(两道思维水题)
- 十几万连接几M的流量,吓死“宝宝”了
- DNS
- ios中json解析出现的null问题
- Yum安装iso光盘中的软件配置
- Maven配置多源代码目录、多资源目录
- Windows2008 R2下,DCOM配置里的属性灰色不可用的解决方法
- 【Mark】项目代码风格要求
- 下拉表单
- Hadoop 源码阅读系列