另一种锁:ReentractLock
1,概述前面我们说了volatile关键字,主要是为了处理并发读写场景,解决可见性的问题。然后又讲了synchronized锁,处理并发写的场景,解决原子性的问题。接着又说了Atomic原子系列,它是基于基本数据类型或者引用来解决原子问题,底层是基于CAS(compare and set),无锁化(乐观锁)。这篇文章主要来说说ReentractLock,先演示一个demo,对ReentractLock有个基本的了解。 public class ReentractLockDemo { #获取一个lock锁 static ReentrantLock lock = new ReentrantLock(); #可修改的共享变量 static volatile int flag = 0; public static void main(String[] args) { new Thread() { @Override public void run() { while (true) { //获取锁 lock.lock(); flag++; System.out.println(Thread.currentThread().getName() + "线程修改变后的变量为" + flag); ?2,AQS(Abstract Queued Synchronizer)2.1 简述抽象队列同步器。经常听到这个词,本文就要分析下这到底是啥含义。并发包的锁都是基于AQS来实现的,一般我们开发是不直接接触的,它是并发的基础,java并发包底层的API。我们先画个图,了解下AQS的含义: 过程简述一下,当第一个线程获取锁时,将state状态+1,变成了1。此时当前加锁线程为线程1.然后线程2来获取锁,发现state不等于0,也就是有人占有了锁,此时线程2就到一个队列中排队。这时候线程3,线程N会依次来排队挂起。线程1处理任务完毕,将会唤醒队列中的线程,然后线程就去争取锁,获取到锁的线程就会出队列,重新改变state的值,将当前线程变为自己的。 ? 大体过程如上所示,不过这样说起来还是太抽象了。我们从源码中去探索,看看是为啥叫AQS,队列是怎么实现的,怎么就实现了锁的功能了。。。 ? 2.2 源码剖析首先看看ReentrantLock的构造函数。 public ReentrantLock() { 通过上面的源代码,就知道了ReentrantLock里面有内部类:NonfairSync、FairSync、Sync。NonfairSync、FairSync是Sync的子类,其中NonfailSync是默认构造函数实现的(也就是非公平锁,后面会讲解它和FairSync的区别)。而且ReentrantLock就是一个外壳,真正功能的实现就是Sync这些对象。我们再看看Sync这个类,发现他是一个抽象类,继承了AbstractQueuedSynchronizer这个类。源码如下: abstract static class Sync extends AbstractQueuedSynchronizer ?这时候发现AbstractQueuedSynchronizer。也就是我们之前说的AQS,抽象队列同步器。很明显了,核心的方法都应该在AbstractQueuedSynchronizer类里面了。来看看AbstractQueuedSynchronizer的核心的字段:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |