iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java重写锁的设计结构和细节是什么
  • 121
分享到

Java重写锁的设计结构和细节是什么

2023-06-29 11:06:26 121人浏览 薄情痞子
摘要

这篇文章主要介绍“Java重写锁的设计结构和细节是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java重写锁的设计结构和细节是什么”文章能帮助大家解决问题。引导语有的面试官喜欢让同学在说完锁的

这篇文章主要介绍“Java重写的设计结构和细节是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java重写锁的设计结构和细节是什么”文章能帮助大家解决问题。

    引导语

    有的面试官喜欢让同学在说完锁的原理之后,让你重写一个新的锁,要求现场在白板上写出大概的思路和代码逻辑,这种面试题目,蛮难的,我个人觉得其侧重点主要是两个部分:

    考察一下你对锁原理的理解是如何来的,如果你对源码没有解读过的话,只是看看网上的文章,或者背面试题,也是能够说出大概的原理,但你很难现场写出一个锁的实现代码,除非你真的看过源码,或者有和锁相关的项目经验;

    我们不需要创造,我们只需要模仿 Java 锁中现有的 api 进行重写即可。

    如果你看过源码,这道题真的很简单,你可以挑选一个你熟悉的锁进行模仿。

    1、需求

    一般自定义锁的时候,我们都是根据需求来进行定义的,不可能凭空定义出锁来,说到共享锁,大家可能会想到很多场景,比如说对于共享资源的读锁可以是共享的,比如对于数据库链接的共享访问,比如对于 Socket 服务端的链接数是可以共享的,场景有很多,我们选择共享访问数据库链接这个场景来定义一个锁。

    2、详细设计

    假定(以下设想都为假定)我们的数据库是单机 mysql,只能承受 10 个链接,创建数据库链接时,我们是通过最原始 JDBC 的方式,我们用一个接口把用 JDBC 创建链接的过程进行了封装,这个接口我们命名为:创建链接接口。

    共享访问数据库链接的整体要求如下:所有请求加在一起的 Mysql 链接数,最大不能超过 10(包含 10),一旦超过 10,直接报错。

    在这个背景下,我们进行了下图的设计:

    Java重写锁的设计结构和细节是什么

    这个设计最最关键的地方,就是我们通过能否获得锁,来决定是否可以得到 mysql 链接,如果能获得锁,那么就能得到链接,否则直接报错。

    接着我们一起来看下落地的代码:

    2.1、定义锁 

    首先我们需要定义一个锁出来,定义时需要有两个元素:

    锁的定义:同步器 Sync;锁对外提供的加锁和解锁的方法。

    共享锁的代码实现如下:

    // 共享不公平锁public class ShareLock implements Serializable{// 同步器  private final Sync sync;  // 用于确保不能超过最大值  private final int maxCount;    public ShareLock(int count) {    this.sync = new Sync(count);    maxCount = count;  }    public boolean lock(){    return sync.acquireByShared(1);  }    public boolean unLock(){    return sync.releaseShared(1);  }}

    从上述代码中可以看出,加锁和释放锁的实现,都依靠同步器 Sync 的底层实现。

    唯一需要注意的是,锁需要规定好 API 的规范,主要是两方面:

    API 需要什么,就是锁在初始化的时候,你需要传哪些参数给我,在 ShareLock 初始化时,需要传最大可共享锁的数目;

    需要定义自身的能力,即定义每个方法的入参和出参。在 ShareLock 的实现中,加锁和释放锁的入参都没有,是方法里面写死的 1,表示每次方法执行,只能加锁一次或释放锁一次,出参是布尔值,true 表示加锁或释放锁成功,false 表示失败,底层使用的都是 Sync 非公平锁。

    以上这种思考方式是有方法论的,就是我们在思考一个问题时,可以从两个方面出发:API 是什么?API 有什么能力?

    2.2、定义同步器 Sync

    Sync 直接继承 AQS ,代码如下:

    class Sync extends AbstractQueuedSynchronizer {   // 表示最多有 count 个共享锁可以获得  public Sync(int count) {    setState(count);  }  // 获得 i 个锁  public boolean acquireByShared(int i) {    // 自旋保证 CAS 一定可以成功    for(;;){      if(i<=0){        return false;      }      int state = getState();      // 如果没有锁可以获得,直接返回 false      if(state <=0 ){        return false;      }      int expectState = state - i;      // 如果要得到的锁不够了,直接返回 false      if(expectState < 0 ){        return false;      }      // CAS 尝试得到锁,CAS 成功获得锁,失败继续 for 循环      if(compareAndSetState(state,expectState)){        return true;      }    }  }  // 释放 i 个锁  @Override  protected boolean tryReleaseShared(int arg) {    for(;;){      if(arg<=0){        return false;      }      int state = getState();      int expectState = state + arg;      // 超过了 int 的最大值,或者 expectState 超过了我们的最大预期      if(expectState < 0 || expectState > maxCount){        log.error("state 超过预期,当前 state is {},计算出的 state is {}",state        ,expectState);        return false;      }      if(compareAndSetState(state, expectState)){        return true;      }    }  }}

    整个代码比较清晰,我们需要注意的是:

    边界的判断,比如入参是否非法,释放锁时,会不会出现预期的 state 非法等边界问题,对于此类问题我们都需要加以判断,体现出思维的严谨性;

    加锁和释放锁,需要用 for 自旋 + CAS 的形式,来保证当并发加锁或释放锁时,可以重试成功。写 for 自旋时,我们需要注意在适当的时机要 return,不要造成死循环,CAS 的方法 AQS 已经提供了,不要自己写,我们自己写的 CAS 方法是无法保证原子性的。

    2.3、通过能否获得锁来决定能否得到链接

    锁定义好了,我们需要把锁和获取 Mysql 链接结合起来,我们写了一个 Mysql 链接的工具类,叫做 MysqlConnection,其主要负责两大功能:

    通过 JDBC 建立和 Mysql 的链接;

    结合锁,来防止请求过大时,Mysql 的总链接数不能超过 10 个。

    首先我们看下 MysqlConnection 初始化的代码:

    public class MysqlConnection {  private final ShareLock lock;  // maxConnectionSize 表示最大链接数  public MysqlConnection(int maxConnectionSize) {    lock = new ShareLock(maxConnectionSize);  }}

    我们可以看到,在初始化时,需要制定最大的链接数是多少,然后把这个数值传递给锁,因为最大的链接数就是 ShareLock 锁的 state 值。

    接着为了完成 1,我们写了一个 private 的方法:

    // 得到一个 mysql 链接,底层实现省略private Connection getConnection(){}

    然后我们实现 2,代码如下:

    // 对外获取 mysql 链接的接口// 这里不用try finally 的结构,获得锁实现底层不会有异常// 即使出现未知异常,也无需释放锁public Connection getLimitConnection() {  if (lock.lock()) {    return getConnection();  }  return null;}// 对外释放 mysql 链接的接口public boolean releaseLimitConnection() {  return lock.unLock();}

    逻辑也比较简单,加锁时,如果获得了锁,就能返回 Mysql 的链接,释放锁时,在链接关闭成功之后,调用 releaseLimitConnection 方法即可,此方法会把锁的 state 状态加一,表示链接被释放了。

    以上步骤,针对 Mysql 链接限制的场景锁就完成了。

    3、测试

    锁写好了,接着我们来测试一下,我们写了一个测试的 demo,代码如下:

    public static void main(String[] args) {  log.info("模仿开始获得 mysql 链接");  MysqlConnection mysqlConnection = new MysqlConnection(10);  log.info("初始化 Mysql 链接最大只能获取 10 个");  for(int i =0 ;i<12;i++){    if(null != mysqlConnection.getLimitConnection()){      log.info("获得第{}个数据库链接成功",i+1);    }else {      log.info("获得第{}个数据库链接失败:数据库连接池已满",i+1);    }  }  log.info("模仿开始释放 mysql 链接");  for(int i =0 ;i<12;i++){    if(mysqlConnection.releaseLimitConnection()){      log.info("释放第{}个数据库链接成功",i+1);    }else {      log.info("释放第{}个数据库链接失败",i+1);    }  }  log.info("模仿结束");}

    以上代码逻辑如下:

    获得 Mysql 链接逻辑:for 循环获取链接,1~10 都可以获得链接,11~12 获取不到链接,因为链接被用完了;释放锁逻辑:for 循环释放链接,1~10 都可以释放成功,11~12 释放失败。

    我们看下运行结果,如下图:

    Java重写锁的设计结构和细节是什么

    从运行的结果,可以看出,我们实现的 ShareLock 锁已经完成了 Mysql 链接共享的场景了。

    关于“Java重写锁的设计结构和细节是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网精选频道,小编每天都会为大家更新不同的知识点。

    --结束END--

    本文标题: Java重写锁的设计结构和细节是什么

    本文链接: https://www.lsjlt.com/news/324550.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • Java重写锁的设计结构和细节是什么
      这篇文章主要介绍“Java重写锁的设计结构和细节是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java重写锁的设计结构和细节是什么”文章能帮助大家解决问题。引导语有的面试官喜欢让同学在说完锁的...
      99+
      2023-06-29
    • Java源码解析重写锁的设计结构和细节
      目录引导语1、需求2、详细设计2.1、定义锁 2.2、定义同步器Sync2.3、通过能否获得锁来决定能否得到链接3、测试4、总结 引导语 有的面试官喜欢让同学在说...
      99+
      2024-04-02
    • Java字节码结构是什么
      这篇文章主要讲解了“Java字节码结构是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java字节码结构是什么”吧!1. 字节码1.1 什么是字节码?Java之所以可以“一次编译,到处运...
      99+
      2023-06-03
    • C++ 函数重载和重写与类层次结构的设计原则
      函数重载和重写简介c++++ 中的函数重载和重写允许同名函数具有不同的参数列表或覆盖基类中的同名函数,以实现更灵活和可扩展的代码,并遵循重要原则(如 srp、lsp、dip)。 C++...
      99+
      2024-04-20
      函数重载 类层次结构 c++ lsp
    • 什么是结构化程序设计
      结构化程序设计是一种使程序更加清晰、易于理解和维护的编程方法论。通过将程序划分为不同的模块,并使用控制结构来组织这些模块,结构化程序设计使程序的开发和维护更加高效和可靠,无论是初学者还是有经验的开发者,都应该掌握结构化程序设计的基本原理和技...
      99+
      2023-08-14
    • Java分支结构程序设计方法是什么
      这篇“Java分支结构程序设计方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java分支结构程序设计方法是什么”文...
      99+
      2023-06-29
    • web设计模式隐藏产品的细节是什么
      本篇内容主要讲解“web设计模式隐藏产品的细节是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“web设计模式隐藏产品的细节是什么”吧!隐藏产品实现细节假设我们有一个LED显示系统,这个系统提...
      99+
      2023-06-19
    • Java和JVM的重载和重写方法是什么
      本文小编为大家详细介绍“Java和JVM的重载和重写方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java和JVM的重载和重写方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.案例void&...
      99+
      2023-06-28
    • MySQL中的常用树形结构设计是什么
      今天小编给大家分享一下MySQL中的常用树形结构设计是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. 递归表idpi...
      99+
      2023-07-05
    • Java中super关键字的用法和细节是什么
      这篇文章将为大家详细讲解有关Java中super关键字的用法和细节是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Java的优点是什么1. 简单,只需理解基本的概念,就可以编写适合于各种...
      99+
      2023-06-26
    • java Dubbo架构整体设计方法是什么
      这篇文章主要介绍“java Dubbo架构整体设计方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“java Dubbo架构整体设计方法是什么”文章能帮助大家解决问题。一、Dubbo调用关系说...
      99+
      2023-07-06
    • Java实现读写锁的原理是什么
      本文小编为大家详细介绍“Java实现读写锁的原理是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java实现读写锁的原理是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。读/写锁Java实现首先我们总结一...
      99+
      2023-06-29
    • java读写锁的使用方法是什么
      在Java中,读写锁是一种特殊的锁,允许多个线程同时读取共享资源,但只允许一个线程进行写操作。读写锁通过ReadWriteLock接...
      99+
      2024-04-03
      java
    • Python中的分支结构和循环结构是什么
      这篇文章主要介绍“Python中的分支结构和循环结构是什么”,在日常操作中,相信很多人在Python中的分支结构和循环结构是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python中的分支结构和循环结构...
      99+
      2023-06-02
    • java读写锁的工作原理是什么
      读写锁是一种特殊的锁机制,允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。读写锁的工作原理如下: 当一个线程想要读取...
      99+
      2024-04-03
      java
    • 什么是Java编程中的数据结构和算法?
      Java编程中的数据结构和算法是指在Java编程中,使用各种数据结构和算法来解决问题。数据结构是指在计算机科学中,用来组织和存储数据的方式和方法,而算法是指用来解决问题的一系列步骤和规则。 Java是一种面向对象的编程语言,其内置了许多数据...
      99+
      2023-09-25
      编程算法 laravel 对象
    • PHP7中zval结构和引用计数机制是什么
      这篇文章主要介绍PHP7中zval结构和引用计数机制是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!最近在查阅 PHP7 垃圾回收的资料的时候,网上的一些代码示例在本地环境下运行时出现了不同的结果,使我一度非常迷...
      99+
      2023-06-14
    • java应用程序的结构是什么
      Java应用程序的结构可以大致分为以下几个部分:1. 导入包(Import Statements):在Java应用程序中,需要使用一...
      99+
      2023-09-27
      java
    • openstack的架构设计原则是什么
      OpenStack的架构设计原则包括以下几个方面: 模块化和可扩展性:OpenStack的架构采用模块化设计,将不同功能的组件划...
      99+
      2023-10-25
      openstack
    • rainbond的架构设计原理是什么
      这篇“rainbond的架构设计原理是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“rainbond的架构设计原理是什么...
      99+
      2023-06-29
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作