ReentrankLock  分为 非公平锁及公平锁

首先我们看一下它里面有哪些属性:

private final Sync sync;

Sync 这个类是 ReentrantLock的 一个静态内部类,实现了AbstractQueuedSynchronizer 

ReentrantLock根据传入构造方法的布尔型参数实例化出Sync的实现类FairSync和NonfairSync,分别表示公平的Sync和非公平的Sync

AbstractQueuedSynchronizer这个类中封装了同步过程中堵塞的线程队列,它里面对线程之间的切换,同步的占用,做了很好的处理

像CountDownLatch、FutureTask、Semaphore、ReentrantLock等都有一个内部类是这个抽象类的子类

下面我们介绍几个ReentrantLock的核心方法及属性:
private volatile int state;

这个属性初始化为0,表示当前没有加锁,每次lock()操作,便会累加这个值,同样一个线程想要获取这个锁,做CAS操作的时候,也是判断state的值是否为0
NonfairSync锁:

   final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}

fairSync锁:
final void lock() {    acquire(1);}

tryAcquire方法中,先 判断当前state值是否是0,若为0 ,则可进行尝试加锁。若不为0,判断作这个加锁操作的是否为当前线程,若为当前线程,则直接累加,然后更新state值

setExclusiveOwnerThread(current)  是设置当前线程为占有线程

fairSync锁:

    protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (!hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}

NonfairSync锁:final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;
}

同样,unlock(),则会在这个值 上进行-1。从代码上看最终会调用tryRelease 方法,我们可以看到之后在state值为0的时候,才会清空当前占有线程。当state为0时,tryRelease 返回的则是true, 则会判断head是否为null(不为空则表示有阻塞线程,这里阻塞队列这里怎么处理,可以看AbstractQueuedSynchronizer的处理,参考:http://www.cnblogs.com/xrq730/p/4979021.html)之后,会进行unparkSuccessor()的处理,这个方法是AbstractQueuedSynchronizer的方法最终会调用LockSupport.unpark(s.thread);s.thread 为阻塞队列中的一个线程,应该是最接近head的阻塞线程(head为阻塞队列的头指针)
public void unlock() {sync.release(1);}
public final boolean release(int arg) {if (tryRelease(arg)) {Node h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h);return true;}return false;
}

protected final boolean tryRelease(int releases) {int c = getState() - releases;if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;if (c == 0) {free = true;setExclusiveOwnerThread(null);}setState(c);return free;
}

在看JDK源代码的时候,我们会经常的看到try开头的方法,这些方法都是无锁的方式,通过CAS进行多次尝试,会自旋式的获取锁,只有在一定时间内,仍没有获取到锁,才会进行park操作(unsafe的park操作,将线程挂起)

final Thread getOwner()
获取当前占有线程
final int getHoldCount()

获取当前的state值
public final int getQueueLength()

获取阻塞队列的长度

最后,附上简单的使用代码:
public class ReentrantLockDemo {private static int i=0;public static void main(String[] args) throws InterruptedException {final ReentrantLock myLock = new ReentrantLock();Thread thread1=new Thread(new Runnable() {@Overridepublic void run() {for(int j=0;j<1000;j++){myLock.lock();i++;try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}myLock.unlock();}}});Thread thread2=new Thread(new Runnable() {@Overridepublic void run() {for(int j=0;j<1000;j++){myLock.lock();i++;try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}myLock.unlock();}}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println(i);}
}

 


转载于:https://www.cnblogs.com/lizhiyan-world/p/6896759.html

ReentrantLock深入学习相关推荐

  1. 【并发编程】线程锁--Synchronized、ReentrantLock(可重入锁)

    在说锁之前,我们要明白为什么要加锁,不加锁会怎样? 在并发编程中,很容易出现线程安全问题,接下来我们看个很经典的例子--银行取钱,来看一下有关线程安全的问题. 取钱的流程可以分为一下几个步骤: 1.用 ...

  2. ReentrantLock 中的 4 个坑!

    作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) JDK 1.5 之前 synchronized 的性能是比较低的,但在 JDK 1 ...

  3. Java锁(二):AbstractQueuedSynchronizer、ReentrantLock详解

    一.AbstractQueuedSynchronizer简介 AQS(AbstractQueuedSynchronizer)是并发容器JUC(java.util.concurrent)下locks包内 ...

  4. Java高并发编程基础之AQS

    引言 曾经有一道比较比较经典的面试题"你能够说说java的并发包下面有哪些常见的类?"大多数人应该都可以说出 CountDownLatch.CyclicBarrier.Sempah ...

  5. 争时金融java_Java高并发编程基础之AQS

    引言 曾经有一道比较比较经典的面试题"你能够说说java的并发包下面有哪些常见的类?"大多数人应该都可以说出 CountDownLatch.CyclicBarrier.Sempah ...

  6. ReentrantLock学习

    对于并发工作,你需要某种方式来防止两个任务访问相同的资源,至少在关键阶段不能出现这种冲突情况.防止这种冲突的方法就是当资源被一个任务使用时,在其上加锁.在前面的文章--synchronized学习中, ...

  7. JAVA——以ReentrantLock为例学习重入锁以及公平性问题

    关注微信公众号:CodingTechWork,一起学习交流进步. 引言   重入锁,顾名思义在于这个重字.开发过程中,我们在用到锁时,可能会用于递归的方法上加锁,此时,那同一个方法对象去重复加锁,是怎 ...

  8. Java并发学习笔记:ReentrantLock

    锁的获取主要是这两个函数,当然还有 lockInterruptibly( ) 和 tryLock(long timeout, TimeUnit unit) 这种响应中断和带时间限制的函数,不过和普通的 ...

  9. 并发编程(入门) 多线程学习 手写ReentrantLock

    本文学习资料和灵感来自网络,感谢享学课堂13号技师.开课吧小师妹.汪文君老师.<Java并发编程实战>[Brian Goetz] 一:概述 随着java技术的成熟和工作年限的增长,现在出去 ...

  10. 【多线程学习笔记】sychronized关键字底层原理、sychronized与ReentrantLock、volatile和synchronized

    文章目录 sychronized释义 synchronized关键字最主要的三种使用方式: synchronized底层原理: 同步代码块: 同步方法 当前类的class对象作为锁 锁升级 Synch ...

最新文章

  1. 每位开发人员都应铭记的10句编程谚语 (我超喜欢,转载了)
  2. ubuntu安装QQ
  3. 正则表达式的兼容性问题
  4. C# WPF 中用代码模拟鼠标和键盘的操作
  5. 11.2 滑动窗口-机器学习笔记-斯坦福吴恩达教授
  6. 在浙学计算机基础2020答案,浙江大学2020年硕士研究生复试分数线的基本要求
  7. 向前欧拉公式 matlab_你可能不知道的MATLAB操作#第三话
  8. 如何查看apache,php,mysql的编译参数
  9. 将x86平台的Linux控制台重定向到串口
  10. AF_INET是什么?
  11. 计算机五笔打字口诀,五笔打字口诀
  12. 一、CRUB的使用及如何终端关机
  13. Word随手记:关于Word中大括号内的多行公式对齐问题
  14. 2018AHU新生赛Panelatta与华容道题解
  15. 2023真无线蓝牙耳机推荐:高性价比真无线蓝牙耳机各价位蓝牙耳机推荐!
  16. 将土豆或者youku 的视频放到自己的网站上面.
  17. 计算机视觉之三维重建——深入浅出SFM系统与SLAM系统的核心算法
  18. JAVA 数据库连接池系列 —— HikariCP 简介
  19. cocoa pods
  20. 线元法输入曲线要素_UG编程建模环境曲线倒圆角的方法

热门文章

  1. LINUX FFMPEG编译详细过程记录(最全)
  2. 重新编译Telepresence,谈如何写编译脚本
  3. LINUX获取当前用户及信息的命令
  4. 编译OpenJDK:invalid configuration Files: machine Files not recognized
  5. 不宜佩带佛像,宜佩带佛号、咒语
  6. 如何删除win10的windows.old
  7. SPFA算法判断负环
  8. Floyd算法 求多源汇最短路
  9. 64位 内存占用大 嵌入式_懵!面试官问我:Object o = new Object() 占用了多少个字节?...
  10. image.open()得到的图片是什么类型_复古门窗花格图片大全让精彩生活继续闪耀 「巴森」...