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中提供的锁是可重入的,因此不会有任何问题。

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

  • 释放finally块中的所有锁。 这是规则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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374122.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

找出互联网类似以下图的实例

转载于:https://www.cnblogs.com/sghcjy/p/4978851.html

python比较运算符重载_python运算符重载

1、打印操作会首先尝试__str__和str内置函数&#xff0c;他通常返回一个用户友好显示。__repr__用于所有其他环境&#xff0c;用于交互式模式下提示回应以及repr函数&#xff0c;如果没有使用__str__&#xff0c;则会使用print和str。它通常返回一个编码字符串&#xff0c;可以…

使用Spring MVC开发Restful Web服务

REST简介 摘自Wikipedia&#xff1a; REST风格的体系结构由客户端和服务器组成。 客户端向服务器发起请求&#xff1b; 服务器处理请求并返回适当的响应。 请求和响应围绕资源表示的传递而构建。 资源本质上可以是可以解决的任何连贯且有意义的概念。 正如您所阅读的&#xff0…

深入Java核心 Java内存分配原理精讲

深入Java核心 Java内存分配原理精讲 Java内存分配与管理是Java的核心技术之一&#xff0c;之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识&#xff0c;今天我们再次深入Java核心&#xff0c;详细介绍一下Java在内存分配方面的知识。一般Java在内存分配时…

iOS正则表达式(亲测,持续更新)

先来说说判断方法,书写不简介但是好理解: -(BOOL)isRealNmaeString:(NSString *)str{NSString *pattern "填写正则表达式";NSPredicate *pred [NSPredicate predicateWithFormat:"SELF MATCHES %", pattern];BOOL isMatch [pred evaluateWithObject:str…

python新建一个文件夹需要重新安装模块吗_解决pycharm每次新建项目都要重新安装一些第三方库的问题...

目前有三个解决办法&#xff0c;也是亲测有用的&#xff1a;第一个方法&#xff1a;因为之前有通过pycharm的project interpreter里的号添加过一些库&#xff0c;但添加的库只是指定的项目用的&#xff0c;如果想要用&#xff0c;就必须用之前的项目的python解释器&#xff0c;…

端到端测试的滥用–测试技术2

我的上一个博客是有关测试代码方法的一系列博客中的第一篇&#xff0c;概述了使用一种非常常见的模式从数据库检索地址的简单方案&#xff1a; …并描述了一种非常通用的测试技术&#xff1a; 不编写测试 &#xff0c; 而是手动进行所有操作。 今天的博客涵盖了另一种实践&…

[AlwaysOn Availability Groups]排查:AG超过RPO

[AlwaysOn Availability Groups]排查&#xff1a;AG超过RPO 排查&#xff1a;AG超过RPO 在异步提交的secondary上执行了切换&#xff0c;你可能会发现数据的丢失大于RPO&#xff0c;或者在计算可以忍受的数据都是超过了RPO。 1.通常原因 1.网络延迟太高&#xff0c;网络吞吐量太…

那些年困扰我们的Linux 的蠕虫、病毒和木马

虽然针对Linux的恶意软件并不像针对Windows乃至OS X那样普遍&#xff0c;但是近些年来&#xff0c;Linux面临的安全威胁却变得越来越多、越来越严重。个中原因包括&#xff0c;手机爆炸性的普及意味着基于Linux的安卓成为恶意黑 客最具吸引力的目标之一&#xff0c;以及使用Lin…

python单元测试框架unittest介绍和使用_Python+Selenium框架设计篇之-简单介绍unittest单元测试框架...

前面文章已经简单介绍了一些关于自动化测试框架的介绍&#xff0c;知道了什么是自动化测试框架&#xff0c;主要有哪些特点&#xff0c;基本组成部分等。在继续介绍框架设计之前&#xff0c;我们先来学习一个工具&#xff0c;叫unittest。unittest是一个单元测试框架&#xff0…

使用PowerMock模拟静态方法

在最近的博客中&#xff0c;我试图强调使用依赖注入的好处&#xff0c;并表达一种想法&#xff0c;即这种技术的主要好处之一是&#xff0c;通过在类之间提供高度的隔离&#xff0c;它可以使您更轻松地测试代码&#xff0c;并且得出的结论是&#xff0c;许多好的测试等于好的代…

多态之向上转型

//向上转型&#xff0c;子类引用指向父类对象 public class UpcastingDemo{ public static void main(String[] args){ Employee enew Employee(); System.out.println(e.grade); e.job(); e.run(); System.out.println("\n"); Manager mnew Manager(…

(转)FPGA异步时序和多时钟模块

http://bbs.ednchina.com/BLOG_ARTICLE_3019907.HTM 第六章 时钟域 有一个有趣的现象&#xff0c;众多数字设计特别是与FPGA设计相关的教科书都特别强调整个设计最好采用唯一的时钟域。换句话说&#xff0c;只有一个独立的网络可以驱动一个设计中所有触发器的时钟端口。虽然…

穆里尼奥:与范加尔风格不同,转变需要时间

据英媒报道&#xff0c;曼联主帅穆里尼奥近日向媒体表示自己很难继续遵循前任主帅范加尔的理念去建立球队&#xff0c;因为他们两人有着完全不同的想法。 穆里尼奥近日在接受BT Sport的采访时表示&#xff1a;“这份工作对于我来说最难的地方便是我与范加尔是非常不同的教练&am…

怎么检测不到我的音频_Linux 上的最佳音频编辑工具推荐 | Linux 中国

在 Linux 上&#xff0c;有很多种音频编辑器可供你选用。不论你是一个专业的音乐制作人&#xff0c;还是只想学学怎么做出超棒的音乐的爱好者&#xff0c;这些强大的音频编辑器都是很有用的工具。-- Ankush Das(作者)在 Linux 上&#xff0c;有很多种音频编辑器可供你选用。不论…

具有GlassFish和一致性的高性能JPA –第3部分

在我的四部分系列的第三部分中&#xff0c;我将解释将Coherence与EclipseLink和GlassFish结合使用的第二种策略。 这就是通过EclipseLink使用Coherence作为二级缓存&#xff08;L2&#xff09;的全部内容。 一般的做法 这种方法将Coherence数据网格应用于依赖于无法完全预加载到…

接口使用时注意

interface Service{ void doSome(); //方法的默认修饰符为public abstract } public class InterfaceNote implements Service{ //方法默认的修饰符为 default void doSome(){ System.out.println("做一些服务&#xff01;"); } public static void main(String…

【Hexo】deploy出错的解决方法

1、ERROR Deployer not found: git 执行npm install hexo-deployer-git --save 2、$ hexo d INFO Deploying: git INFO Clearing .deploy_git folder... INFO Copying files from public folder... fatal: Not a git repository (or any of the parent directories): .git F…

精选30道Java笔试题解答(转)

都是一些非常非常基础的题&#xff0c;是我最近参加各大IT公司笔试后靠记忆记下来的&#xff0c;经过整理献给与我一样参加各大IT校园招聘的同学们&#xff0c;纯考Java基础功底&#xff0c; 老手们就不用进来了&#xff0c;免得笑话我们这些未出校门的孩纸们&#xff0c;但是I…

list取值_Redis中List及quicklist实现-2

上一篇中看了List的使用方式、quicklist中的各个结构体&#xff0c;这一篇来看看quicklist里面的几个核心函数&#xff0c;quicklistCreate函数、quicklistCreateNode函数、quicklistPush函数、quicklistPop函数。接下来我们通过源码看一下quicklist中是如何借鉴STL中deque的这…