锁的作用

  1. 控制多个线程访问共享资源。
  2. 线程协作

Lock接口

特点

  1. 与synchronized类似的同步功能,只是需要显式地获取和释放锁。缺少隐式获取锁的便捷性。
  2. 拥有锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种同步特性。
  3. 可扩展性好。
  4. 尝试非阻塞地获取锁:如果当前时刻锁没有被占用,则获得锁。
  5. 能被中断地获取锁:获得锁的线程能被中断,当获得锁的线程被中断,中断异常会被抛出,然后锁会被释放 。
  6. 超时获取锁:在一定时间内尝试获取锁,如果超时,就返回。

使用方式

Lock lock = new ReentrantLock();
lock.lock(); try {
doSomething();
} finally {
lock.unlock();
}

注意点

  1. 在finally中释放锁,可以保证在获取锁之后,最终能够得到释放 。
  2. 不要将获取锁放在try中,因为可能发生异常,没有获得锁,最后在finally中导致锁的释放。

API

队列同步器

作用

是用来构建锁或者其他同步组件的基础框架。面向锁的是闲着,简化了锁的实现方式。

实现原理

1. 同步队列

依赖一个FIFO双向队列,当前线程获取同步状态失败的时候,就会把线程及其状态信息做成一个节点入队,并阻塞当前线程。当同步状态释放的时候,就唤醒首节点,进行获取同步状态。

队列中的节点用来保存获取同步状态失败的线程引用、等待状态以及前驱和后继节点。用过CAS算法设置尾节点。

当首节点获取同步状态成功时候,就会在释放的时候,唤醒后继节点,然后后继将自己设置为首节点。

2.独占式同步状态获取与释放

每个节点都在自旋,如果前驱节点是头节点,就尝试获取同步状态;不是就进入等待状态。

3.共享式同步状态获取与释放

读操作可以是共享,而写操作是独占。

通过嗲用同步器的acquireShared方法可以共享式地获取同步状态。

同步队列总结

  1. 是一个获取锁的实现框架,让需要竞争一个锁的线程排队,高效获取。
  2. 如果不能马上获取锁,那么这个线程会进入等待状态,而不是一直去尝试获取,这样降低了开销。

重入锁

特点

  1. 支持线程对资源的重复加锁。
  2. 支持获取锁时的公平和非公平性选择。

实现重进入

重进入是指线程在获取到锁之后,这个线程再去获取这把锁,不会被这把锁阻塞。

  1. 再次获取:锁需要是被当前线程是否是已经获得自己的线程,如果是,则再次成功获取。
  2. 最终释放:获取了几次,就要释放几次,这样才能让其他线程获取到这把锁。

公平性与非公平性

  1. 什么是公平性?就是根据线程等待时间的长短,确定哪个线程先获取到锁。
  2. 公平性的问题。非公平的锁开销更小。因为公平性锁采用了FIFO原则将等待线程放进队列,代价是大量的线程切换。

读写锁

特点

  1. 不是排他锁,同一时刻可以允许多个读线程访问;
  2. 但是同一时刻只能由一个写线程访问。
  3. 通过读锁和写锁分离,提高并发性。

实现原理

  1. 写锁是一个支持冲入的排他锁。
  2. 读锁是一个支持重入的共享锁。每次有一个新的线程获取锁,锁状态就增加,这样,如果有写线程想要获取锁就会被阻塞,直到读锁都被释放的时候,写锁才能被获取。
  3. 锁降级。当前线程中的获取的写锁降级为读锁,就是锁降级。过程是:先获取写锁,再获取读锁,最后释放写锁。目的是防止直接放弃写锁之后,其他线程获取到写锁,并修改数据。

使用方式

List<Integer> data = new ArrayList<>();
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
Lock r = rwl.readLock();
Lock w = rwl.writeLock(); public int get(int idx) {
r.lock();
try {
return data.get(idx);
} finally {
r.unlock();
}
} public void add(int num) {
w.lock();
try {
data.add(num);
} finally {
w.unlock();
}
}

LockSupport工具

作用

用于阻塞或唤醒一个线程的公共静态方法。

API

Condition 接口

作用

与Lock配合使用,实现等待和通知模式。

与对象监视器的区别

使用示例

Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public void conditionWait() throws InterruptedException {
lock.lock();
try {
condition.await();
} finally {
lock.unlock();
}
} public void conditionSignal() throws InterruptedException {
lock.lock();
try {
condition.signal();
} finally {
lock.unlock();
}
}

API

实现原理

和同步队列类似。

1.等待队列

等待队列是一个FIFO的队列,每当一个线程调用await()方法,那么这个线程就会释放锁,并进入等待队列。

2.等待

线程调用await()方法进入等待态。

3. 通知

当调用了signal方法,将会唤醒等待队列德首节点。唤醒之前,会将节点移到同步队列中。为什么要放入同步队列中?排队去获取锁啊。

等待队列总结

condition的等待队列像是同步队列下的一个缓冲,同步队列是竞争锁的队列,只有首节点获取到了锁,如果这个节点的线程调用了await方法,那么那就从同步队列的首节点跑到了等待队列了尾节点。其他线程调用了signal方法,那么等待队列的首就跑到同步队列的尾部,进行排队竞争锁。

Java并发编程的艺术(八)——锁相关的更多相关文章

  1. Java并发编程的艺术(十三)——锁优化

    自旋锁 背景:互斥同步对性能最大的影响是阻塞,挂起和恢复线程都需要转入内核态中完成:并且通常情况下,共享数据的锁定状态只持续很短的一段时间,为了这很短的一段时间进行上下文切换并不值得. 原理:当一条线 ...

  2. Java并发编程的艺术(八)——闭锁、同步屏障、信号量详解

    1. 闭锁:CountDownLatch 1.1 使用场景 若有多条线程,其中一条线程需要等到其他所有线程准备完所需的资源后才能运行,这样的情况可以使用闭锁. 1.2 代码实现 // 初始化闭锁,并设 ...

  3. java并发编程的艺术(一)---锁的基本属性

    本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...

  4. 《Java并发编程的艺术》留给自己以后看的笔记

    <Java并发编程的艺术>这本书特别好,和<深入了解JAVA虚拟机>有一拼,建议做java的都看看,下面全部都是复制书中的部分内容,主要目的是做个笔记,方便以后遇到问题能找到. ...

  5. 读《Java并发编程的艺术》学习笔记(一)

    接下来一个系列,是关于<Java并发编程的艺术>这本书的读书笔记以及相关知识点,主要是为了方便日后多次复习和防止忘记.废话不多说,直接步入主题: 第1章  并发编程的挑战 并发编程的目的是 ...

  6. 《Java并发编程的艺术》读书笔记:二、Java并发机制的底层实现原理

    二.Java并发机制底层实现原理 这里是我的<Java并发编程的艺术>读书笔记的第二篇,对前文有兴趣的朋友可以去这里看第一篇:一.并发编程的目的与挑战 有兴趣讨论的朋友可以给我留言! 1. ...

  7. 读《Java并发编程的艺术》(一)

    离开博客园很久了,自从找到工作,到现在基本没有再写过博客了.在大学培养起来的写博客的习惯在慢慢的消失殆尽,感觉汗颜.所以现在要开始重新培养起这个习惯,定期写博客不仅是对自己学习知识的一种沉淀,更是在督 ...

  8. Java并发编程的艺术读书笔记(2)-并发编程模型

    title: Java并发编程的艺术读书笔记(2)-并发编程模型 date: 2017-05-05 23:37:20 tags: ['多线程','并发'] categories: 读书笔记 --- 1 ...

  9. Java并发编程的艺术读书笔记(1)-并发编程的挑战

    title: Java并发编程的艺术读书笔记(1)-并发编程的挑战 date: 2017-05-03 23:28:45 tags: ['多线程','并发'] categories: 读书笔记 --- ...

  10. Java并发编程的艺术(六)——线程间的通信

    多条线程之间有时需要数据交互,下面介绍五种线程间数据交互的方式,他们的使用场景各有不同. 1. volatile.synchronized关键字 PS:关于volatile的详细介绍请移步至:Java ...

随机推荐

  1. mysql 常用命令和笔记

    第一招.mysql服务的启动和停止 net stop mysql net start mysql 第二招.登陆mysql 语法如下: mysql -u用户名 -p用户密码 键入命令mysql -uro ...

  2. 解决calamari无法获取节点信息的bug

    前言 一直在做calamari的相关的一些打包和安装的工作,都是业余弄的东西,所以并没有仔细的进行功能点的验证测试,正好ceph社区群里面有人问了个问题 calamari上是不是能看到ceph的ver ...

  3. 利用CSS3实现div页面淡入动画特效

    利用CSS3实现页面淡入动画特效   摘要 利用CSS3动画属性"@keyframes "可实现一些动态特效,具体语法和参数可以网上自行学习.这篇文章主要是实践应用一下这个动画属性 ...

  4. Android ContentProvider 启动分析

    对于 ContentProvider 还不是很熟悉的同学,可以阅读上一篇 Android ContentProvider 基本原理和使用详解.本文主要是对 contentProvider 的源码进行分 ...

  5. sqlilab less19-less22

    less19 当账号密码正确时,会将当前的refer和ip存入数据库.对这两个值同时没有进行过滤.考虑使用sqlmap对这两个参数进行注入 less-20 当cookie uname存在时,并且不是p ...

  6. redhat-NFS服务的配置与应用

    ---恢复内容开始--- 1.NFS服务简述 NFS实现Windows系统中资源共享的功能.NFS采用客户/服务器工作模式,客户端将服务器中的共享目录挂载到自己的某个目录下,这个目录可以与其他客户机的 ...

  7. git key生成

    1.打开git ssh 2.检查home目录的ssh目录是否存在,没有创建一个,mkdir ~/.ssh 3.运行命名:ssh-keygen -t rsa -C "你的邮箱", 如 ...

  8. OxyPlot组件的基本使用

    在制作上位机的时候,很多时候需要使用到监控绘图界面,使用来绘制曲线的组件有很多,GDI+.char.OxyPlot等等,这篇文章用来介绍OxyPlot组件的基本应用,在本文中主要是利用随心数生成函数结 ...

  9. 初学者也能轻松做出好Beat:FPC鼓机使用教程

    如果我们想用FL Studio制作一个鼓的声部,这时水果自带的鼓机FPC简直就是我们初学者的福音.因为它的操作比较简单,自带的鼓谱也很丰富,而且我们还可以对鼓的音色做细致的调整,或者是使用自己的采样替 ...

  10. JUC并发工具包之CyclicBarrier & CountDownLatch的异同

    1.介绍 本文我们将比较一下CyclicBarrier和CountDownLatch并了解两者的相似与不同. 2.两者是什么 当谈到并发,将这两者概念化的去解释两者是做什么的,这其实是一件很有挑战的事 ...