java 并发锁

Java的synced关键字是一个很棒的工具–它使我们可以通过一种简单可靠的方式来同步对关键部分的访问,而且也不难理解。

但是有时我们需要对同步进行更多控制。 我们要么需要分别控制访问类型(读取和写入),要么使用起来很麻烦,因为要么没有明显的互斥锁,要么我们需要维护多个互斥锁。

幸运的是,在Java 1.5中添加了锁实用程序类,使这些问题更易于解决。

Java重入锁

Java在java.util.concurrent.locks包中有一些锁实现。

锁的一般类很好地布置为接口:

  • –最简单的锁,可以获取和释放
  • ReadWriteLock –具有读和写锁类型的锁实现–一次可以持有多个读锁,除非持有排他写锁

Java提供了我们关心的这些锁的两种实现–两者都是可重入的(这仅意味着线程可以多次重新获取同一锁而没有任何问题)。

  • ReentrantLock –如您所料,可重入锁实现
  • ReentrantReadWriteLock –可重入ReadWriteLock实现

现在,让我们看一些例子。

读/写锁定示例

那么如何使用锁呢? 这很简单:只需获取并发布(永远不要忘记发布-终于是您的朋友!)。

假设我们有一个非常简单的情况,我们需要同步访问一对变量。 一个是简单的值,另一个是根据一些冗长的计算得出的。 首先,这是我们如何使用synced关键字执行此操作。

public class Calculator {private int calculatedValue;private int value;public synchronized void calculate(int value) {this.value = value;this.calculatedValue = doMySlowCalculation(value);}public synchronized int getCalculatedValue() {return calculatedValue;}public synchronized int getValue() {return value;}
}

很简单,但是如果我们有很多争用,或者执行很多读取而写很少,则同步可能会影响性能。 由于频繁读取比写入频繁得多,因此使用ReadWriteLock可帮助我们最大程度地减少问题:

public class Calculator {private int calculatedValue;private int value;private ReadWriteLock lock = new ReentrantReadWriteLock();public void calculate(int value) {lock.writeLock().lock();try {this.value = value;this.calculatedValue = doMySlowCalculation(value);} finally {lock.writeLock().unlock();}}public int getCalculatedValue() {lock.readLock().lock();try {return calculatedValue;} finally {lock.readLock().unlock();}}public int getValue() {lock.readLock().lock();try {return value;} finally {lock.readLock().unlock();}}
}

此示例实际上显示了使用同步has的一大优势:与使用显式锁相比,此方法简洁明了且更加安全。 但是锁提供了使用灵活性,而这是我们以前所没有的。

在上面的示例中,我们可以让数百个线程一次读取相同的值而没有问题,并且只有在获得写入锁定时才阻塞读取器。 请记住:许多读取器可以同时获取读取锁,但是在获取写入锁时不允许读取器或写入器。

更典型的用途

我们的第一个示例可能会让您感到困惑或不完全相信显式锁是有用的。 难道他们还没有其他用途吗? 当然!

我们在Carfey使用显式锁来解决许多问题。 一个示例是您有可以同时运行的各种任务,但是您不希望同时运行多个相同类型的任务。 一种实现它的干净方法是使用锁。 可以通过同步来完成,但是锁使我们能够在超时后失败。

值得一提的是,您会注意到我们使用了同步锁和显式锁的混合-有时一个比另一个更干净,更简单。

public class TaskRunner {private Map<Class<? extends Runnable>,  Lock> mLocks =new HashMap<Class<? extends Runnable>,  Lock>();public void runTaskUniquely(Runnable r, int secondsToWait) {Lock lock = getLock(r.getClass());boolean acquired = lock.tryLock(secondsToWait, TimeUnit.SECONDS);if (acquired) {try {r.run();} finally {lock.unlock();}} else {// failure code here}}private synchronized Lock getLock(Class clazz) {Lock l = mLocks.get(clazz);if (l == null) {l = new ReentrantLock();mLocks.put(clazz, l);}return l;}
}

这两个示例应该使您对如何同时使用计划ReadWriteLocks有所了解。 与同步一样,不必担心重新获得相同的锁-JDK中提供的锁是可重入的,因此不会有任何问题。

每当您处理并发时,都有危险。 永远记住以下几点:

  • 释放所有锁,使其最终锁​​住。 这是规则1,是有原因的。
  • 当心线程饥饿! 如果您有不想永久等待的许多读者和偶尔的作家,那么ReentrantLocks中的公平设置可能会很有用。 如果其他线程不断持有读取锁,那么编写者有可能等待很长时间(也许永远)。
  • 尽可能使用同步。 您将避免错误并保持代码更清洁。
  • 如果您不希望线程无限期等待获取锁,请使用tryLock() -这类似于数据库具有的等待锁超时。

就是这样! 如果您有任何问题或意见,请随时将其留在下面。

参考: Java并发第2部分–来自JCG合作伙伴的Carent博客上的 Reentrant Locks 。

相关文章 :
  • Java并发教程–信号量
  • Java并发教程–线程池
  • Java并发教程–可调用,将来
  • Java并发教程–阻塞队列
  • Java并发教程– CountDownLatch
  • Exchanger和无GC的Java
  • Java Fork / Join进行并行编程
  • Java最佳实践–队列之战和链接的ConcurrentHashMap
  • 使用迭代器时如何避免ConcurrentModificationException
  • 改善Java应用程序性能的快速技巧

翻译自: https://www.javacodegeeks.com/2011/09/java-concurrency-tutorial-reentrant.html

java 并发锁

java 并发锁_Java并发教程–重入锁相关推荐

  1. java 线程的可重入锁_java 多线程-可重入锁

    可重入锁:锁可以连续使用 计数器+判断进入的线程是不是已经锁定的线程,如果是那就不用等待,直接使用 public class my { public static void main(String[] ...

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

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

  3. Redis核心数据结构List应用场景-商品列表、缓存击穿、PV阅读量、抢红包、推送帖子、普通分布式锁、Redis可重入锁与红锁

    List应用场景 Redis之List 一. Redis list命令实战 二.商品列表 高并发的淘宝聚划算实现技术方案 SpringBoot+Redis实现商品列表功能 二.缓存击穿 什么是缓存击穿 ...

  4. 可重入锁-synchronized是可重入锁吗?

    目录 前言 1.什么是可重入锁呢? 2.自己写代码验证下可重入和不可重入 3.自己如何实现一个可重入和不可重入锁呢 4.ReentrantLock如何实现可重入的 5.可重入锁的特点 前言 面试题:s ...

  5. 可重入锁与非可重入锁

    文章目录 锁的分类 什么是可重入锁 测试lock 锁的可重入性 不可重入锁 锁的分类 什么是可重入锁 可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前 ...

  6. Java并发教程–重入锁

    Java的synced关键字是一个很棒的工具–它使我们能够以一种简单可靠的方式来同步对关键部分的访问,而且也不难理解. 但是有时我们需要对同步进行更多控制. 我们要么需要分别控制访问类型(读取和写入) ...

  7. 并发类编程—ReentrantLock(可重入锁)

    1.概念 ReentantLock继承接口 Lock 并实现了接口中定义的方法,他是一种可重入锁,除了能完成synchronized 所能完成的所有工作外,还提供了中断锁.定时锁等避免多线程死锁的方法 ...

  8. java dom4j读写锁,java锁的深度化-重入锁,读写锁,乐观锁,悲观锁

    1.重入锁 目的:避免死锁的现象 锁作为并发共享数据,保证一致性的工具,在java平台有多种实现synchronized(重量级)和ReentrantLock(轻量级)等等,这些已经写好提供的锁为我们 ...

  9. 什么是可重入锁?为什么需要可重入锁?

    可重入锁,从字面来理解,就是可以重复进入的锁. 可重入锁,也叫做递归锁,指的是同一线程外层函数获得锁之后,内层递归函数仍然有获取该锁的代码,但不受影响. 在JAVA环境下ReentrantLock和s ...

最新文章

  1. dacom蓝牙耳机怎么重置_双蓝牙耳机另一半怎么连接
  2. sql 语句 查询两个字段都相同的方法
  3. 大数据会消灭律师这一职业吗?
  4. JavaScript(19)jQuery HTML 获取和设置内容和属性
  5. CSS中clear属性的both、left和right浅析
  6. django 1.8 官方文档翻译:8-5 加密签名
  7. c# 客户端 服务器传输文件,通过TCP在C++客户端/ C#服务器之间传输文件
  8. 移动前端开发一定会遇上的事
  9. Windows远程桌面开发之九-虚拟显示器(Windows 10 Indirect Display 虚拟显示器驱动开发)
  10. LDA模型困惑度计算出现的问题
  11. 电脑键盘部分按键失灵_Win7系统键盘部分按键失灵了怎么办?
  12. 74HC138三八译码器的应用
  13. 电脑如何同时远程控制多台手机
  14. 【透视课笔记】L2室内空间与人物
  15. 编写程序,实现一个基于面向思想的、具有开户、查询、取款、存款、转账、锁定、解锁和退出功能的银行管理系统。
  16. Ubuntu20.04安装nVidia显卡遇到的各种坑
  17. 删除u盘插拔记录linux,电脑u盘插拔记录_电脑u盘插拔时间记录
  18. Flutter Dio二次封装
  19. 平面几何中点到直线上的投影计算
  20. date java 格式化 sss_Java的日期格式化常用方法

热门文章

  1. 几天没写代码,就……
  2. 《白鹿原》金句摘抄(四)
  3. 银行营业网点管理系统——entity类(CityArea)
  4. JAVA集合(笔记)
  5. 联想linux笔记本评测,联想(lenovo)G460AL-ITH Linux笔记本电脑CPU测试评测-ZOL中关村在线...
  6. html5圆形旋转菜单js,jquery 圆形旋转图片滚动切换效果
  7. SpringBoot连接多RabbitMQ源
  8. XML——文档类型定义(DTD-Document Type Definition)
  9. 多线程的三种实现方法
  10. openhub_OpenHub框架–下一个有趣的功能