本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,需要自己领取。
传送门:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q

和朋友聊天他提到:ReentrantLock 的构造函数可以传递一个 bool 数据,true 时构造的是“公平锁”、false 时构造的是“非公平锁”。我的印象中锁是不区分类型的,所以认为这应该是 Java 发明的概念,于是就恶补了一下。

锁的底层实现

无论什么语言在操作系统层面锁的操作都会变成系统调用(System Call),以 Linux 为例,就是 futex 函数,可以把它理解为两个函数: futex_wait(s),对变量 s 加锁;futex_wake(s)释放 s 上的锁,唤醒其他线程。

在ReentrantLock中很明显可以看到其中同步包括两种,分别是公平的FairSync和非公平的NonfairSync。

公平锁的作用就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的;而非公平锁是允许插队的。

默认情况下ReentrantLock是通过非公平锁来进行同步的,包括synchronized关键字都是如此,因为这样性能会更好。

因为从线程进入了RUNNABLE状态,可以执行开始,到实际线程执行是要比较久的时间的。

而且,在一个锁释放之后,其他的线程会需要重新来获取锁。其中经历了持有锁的线程释放锁,其他线程从挂起恢复到RUNNABLE状态,其他线程请求锁,获得锁,线程执行,这一系列步骤。如果这个时候,存在一个线程直接请求锁,可能就避开挂起到恢复RUNNABLE状态的这段消耗,所以性能更优化。

/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}

默认状态,使用的ReentrantLock()就是非公平锁。再参考如下代码,我们知道ReentrantLock的获取锁的操作是通过装饰模式代理给sync的。

/**
* Acquires the lock.
*
* <p>Acquires the lock if it is not held by another thread and returns
* immediately, setting the lock hold count to one.
*
* <p>If the current thread already holds the lock then the hold
* count is incremented by one and the method returns immediately.
*
* <p>If the lock is held by another thread then the
* current thread becomes disabled for thread scheduling
* purposes and lies dormant until the lock has been acquired,
* at which time the lock hold count is set to one.
*/
public void lock() {
sync.lock();
}

下面参考一下FairSync和NonfairSync对lock方法的实现:

    /**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
} /**
* Sync object for fair locks
*/
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
}

当使用非公平锁的时候,会立刻尝试配置状态,成功了就会插队执行,失败了就会和公平锁的机制一样,调用acquire()方法,以排他的方式来获取锁,成功了立刻返回,否则将线程加入队列,知道成功调用为止。

最新文章

  1. 数组中pop()和reverse()方法调用
  2. iOS 解决导航栏左右 BarButtonItem偏移位置的问题
  3. RestFul API初识
  4. JavaScript----插入视频
  5. SQLServer获取随机数据
  6. Java多态的体现之接口
  7. Magento - get Attribute Options of the dropdown type attribute
  8. AWS Organizations
  9. [读书笔记] 四、SpringBoot中使用JPA 进行快速CRUD操作
  10. windows安装IDEA
  11. C语言学习及应用笔记之七:C语言中的回调函数及使用方式
  12. javascript 之 第七章第三节(this关键字)
  13. select默认显示
  14. 将xml文件由格式化变为压缩字符串
  15. 17秋 软件工程 Alpha展示博客
  16. 多线程:Operation(二)
  17. android之进度条
  18. 廖雪峰网站:学习python函数—调用函数(一)
  19. JAVA 泛型的参数的传递示意图
  20. Install Hyper-V on Windows 10

热门文章

  1. 第三章 学习Shader所需的数学基础(1)
  2. Ubuntu18.04下搭建LNMP教程-超详细图文(Nginx+MySQL+PHP含各种解决报错问题)
  3. MongoDB 谨防索引seek的效率问题【华为云技术分享】
  4. 如何在Android手机上进行自动化测试(上)
  5. 洛谷 P1920 成功密码 题解
  6. mysql-常用组件之触发器
  7. 报错 Please make sure you have the correct access rights and the repository exists (git 添加ssh密钥 )
  8. Sql Server存储过程详解
  9. 【CuteJavaScript】Angular6入门项目(4.改造组件和添加HTTP服务)
  10. redis(6)--redis集群之分片机制(redis-cluster)