一、死磕Java——ReentrantLock

ReentrantLockjava.util.concurrent.locks包下一个可重入的默认是非公平的锁,ReentrantLock类是Lock接口的一个使用很频繁的实现类,类结构如下图:

image-20190508213733422

前面说过JMM模型要求的是可见性原子性有序性。解决原子性的方法也有多种,例如synchronized同步方法或者同步代码块,也可以使用AtomicInteger原子包装类解决,都知道synchronized加锁是最笨重的解决方法,所里,这里使用的是ReentrantLock加锁来实现原子性,代码如下:

class MyData {int num = 0;Lock lock = new ReentrantLock();public void add() {try {lock.lock();num++;} finally {lock.unlock();}}
}
public class ReentrantLockDemo {private static Logger log = LoggerFactory.getLogger(ReentrantLockDemo.class);public static void main(String[] args) {MyData myData = new MyData();for (int i = 1; i <= 20; i++) {new Thread(() -> {for (int j = 1; j <= 1000; j++) {myData.add();}}, String.valueOf(i)).start();}// 知道所有的线程执行结束while (Thread.activeCount() > 1) {Thread.yield();}log.info("结果:{}", myData.num);}
}

1.1.ReentrantLock的公平性

ReentrantLock提供了一个带参数的构造函数,来让使用者决定使用是否是公平锁。

image-20190508215454860

通过源码我们可以知道,无参数就是默认为非公平锁,传入true表示公平锁,传入false表示非公平锁,源码如下

// 空参默认为非公平锁
public ReentrantLock() {sync = new NonfairSync();}
// 根绝参数决定锁的公平性
public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();
}

1.2.ReentrantLock的非公平锁

1.2.1使用ReentrantLock加锁

// 创建一个非公平锁
Lock lock = new ReentrantLock();
try {// 加锁lock.lock();
} finally {// 释放锁lock.unlock();
}

1.2.2.执行的是ReentrantLock的lock方法

 public void lock() {sync.lock();}

1.2.3.调用的是NonfairSync类的lock方法

static final class NonfairSync extends Sync {private static final long serialVersionUID = 7316153563782823691L;/*** Performs lock.  Try immediate barge, backing up to normal* acquire on failure.*/final void lock() {// 通过CAS思想去AQS队列中获取将State值从0变为1,即获取到锁if (compareAndSetState(0, 1))// 获取锁成功则将当前线程标记为持有锁的线程,然后直接返回setExclusiveOwnerThread(Thread.currentThread());else// 获取锁失败则执行该方法acquire(1);}
}

1.2.4.调用AQS的cAS方法获取锁

protected final boolean compareAndSetState(int expect, int update) {// See below for intrinsics setup to support this// unsafe类是通过native方法直接操作内存数据return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

1.2.5.获取锁失败执行acquire方法

public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();
}

先看一下NonfairSync类的继承图,我们可以看见一个很重要的抽象类AbstractQueuedSynchronizer,有关AQS稍后在死磕,可以说AQS是同步组件的基础。

image-20190508221310426

死磕Java——ReentrantLock相关推荐

  1. 死磕Java并发:J.U.C之重入锁:ReentrantLock

    ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机制,可以减 ...

  2. 死磕 java同步系列之ReentrantReadWriteLock源码解析

    问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...

  3. 死磕Java并发:分析 ArrayBlockingQueue 构造函数加锁问题

    作者: chenssy 来源:Java技术驿站 昨天有位小伙伴问我一个 ArrayBlockingQueue 中的一个构造函数为何需要加锁,其实这个问题我还真没有注意过.主要是在看 ArrayBloc ...

  4. 死磕Java并发:J.U.C之阻塞队列:ArrayBlockingQueue

    作者:chenssy 来源:Java技术驿站 ArrayBlockingQueue,一个由数组实现的有界阻塞队列.该队列采用FIFO的原则对元素进行排序添加的. ArrayBlockingQueue为 ...

  5. 死磕Java并发:J.U.C之Java并发容器:ConcurrentLinkedQueue

    作者:chenssy 来源:Java技术驿站 要实现一个线程安全的队列有两种方式:阻塞和非阻塞.阻塞队列无非就是锁的应用,而非阻塞则是CAS算法的应用.下面我们就开始一个非阻塞算法的研究:Coucur ...

  6. 死磕Java并发:J.U.C之并发工具类:Exchanger

    作者:chenssy 来源:Java技术驿站 前面三篇博客分别介绍了CyclicBarrier.CountDownLatch.Semaphore,现在介绍并发工具类中的最后一个Exchange.Exc ...

  7. 死磕Java并发:J.U.C之并发工具类:CountDownLatch

    作者:chenssy 来源:Java技术驿站 在上篇博客中介绍了Java四大并发工具一直的CyclicBarrier,今天要介绍的CountDownLatch与CyclicBarrier有点儿相似. ...

  8. 死磕Java并发:J.U.C之并发工具类:Semaphore

    作者:chenssy 来源:Java技术栈公众号 信号量Semaphore是一个控制访问多个共享资源的计数器,和CountDownLatch一样,其本质上是一个"共享锁". Sem ...

  9. 死磕Java并发:J.U.C之并发工具类:CyclicBarrier

    作者:chenssy 来源:Java技术栈公众号 CyclicBarrier,一个同步辅助类,在API中是这么介绍的: 它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier ...

最新文章

  1. 树莓派/香橙派自建本地DNS加速解析
  2. 宏观相似性与惯性质量
  3. PAT甲级1126 Eulerian Path:[C++题解] 欧拉路径、并查集,测试点4有问题请进来
  4. 机器学习入门学习笔记:(3.2)ID3决策树程序实现
  5. C vector详解
  6. 写在08年“愚人节”
  7. 自己总结的前端面试题
  8. C++ 通讯录管理系统实验报告
  9. android工程改包名及多工程设置
  10. vue自定义组件递归实现树状_一道价值25k的腾讯递归组件面试题(Vue3 + TS 实现)...
  11. R语言ggplot2画图3
  12. 安装Ubuntu镜像和VMware在安装Ubuntu镜像之后开机蓝屏的解决方案
  13. 华硕B85M-D台式机主板音响没反应,更新驱动还是找不到realtek高清晰音频管理器原因及解决方案
  14. IE浏览器F12无法使用
  15. Linux中对的tac命令
  16. 群英传内推第001期
  17. 叠氮PEG叠氮,N3-PEG-N3
  18. 教你一招快速清理DNS缓存
  19. 14.Yum详解,yum安装,查找,info,反向查找,组,依赖,缓存等所有操作
  20. 大小写英文字母对应的ASCII值

热门文章

  1. IT审计中应注意的几个问题(zt)
  2. java基础语法要学多久
  3. 云终端、瘦终端和胖终端三者之间有什么区别
  4. php万能表单源码_震撼!全网第一张源码分析全景图揭秘Nginx
  5. 基于Python的影视推荐系统的实现
  6. 人人都是极客半月刊:第 2 期
  7. html 得到单选按钮的值,js获取单选按钮组选择的值
  8. 如何用光盘映像文件重装服务器系统,韩博士教你如何使用光盘重装系统
  9. 出招吧!腾讯专家手敲《Redis源码日志笔记》,不服来对打!
  10. 隔离芯片1201,直流隔离ICoupler采用的平面磁场技术是一种全新的隔离技术(编码,内部脉冲信号,交流变压器转换)