自定义同步器

自定义同步器

  • 假如你想要实现一个自定义同步器,官方推荐的做法是将继承了AQS类的子类作为自定义同步器的内部类,而自定义同步器中相关的操作只需代理成子类中对应的方法即可。往下用一个简单的例子看看如何实现自己的锁,由于同步器被分为两种模式,独占模式和共享模式,所以例子也对应给出。

独占式

  • 独占模式采取的例子是银行服务窗口,假如某个银行网点只有一个服务窗口,那么此银行服务窗口只能同时服务一个人,其他人必须排队等待。所以这种银行窗口对应的同步器是独占模型。我们先定义一个银行窗口同步器类,它按照官方推荐的做法使用一个继承AQS同步器的子类实现,该子类且为内部类。然后重写tryAcquire和tryRelease方法,获得锁与释放锁的操作主要就是维护同步状态变量,该变量只能为0或1。此外,还提供了handle和unhandle两个方法供使用,其实就是间接调用自定义同步器。

9417315b31ec44e8bf9205702db45670

  • 接着我们定义一个测试类,形象一点来说的话就是有三位良民到银行去办理业务。他们分别是tom、jim和jay,现在我们使用BankServiceWindow同步器就可以约束他们排队,一个一个轮着来办理业务从而避免陷入混乱的局面。
  • bf54d8a2adcb4ad5ab829c241f8e712e
  • 最终输出结果如下,明显tom、jim、jay仨人是排队完成的。但我们是没办法保证三者的顺序的,可能是tom、jim、jay,也可能是tom、jay、jim,因为在入列以前的执行先后是无法确定的。这个同步器的语义是保证一个接一个办理。

tom开始办理业务
tom结束办理业务
jim开始办理业务
jim结束办理业务
jay开始办理业务
jay结束办理业务

共享模式

  • 共享模式采取的例子同样是银行服务窗口,随着银行网点的发展,办理业务的人越来越多,一个服务窗口已经无法满足需求。于是分配了另外一位员工开了另外一个服务窗口,这时就可以同时服务两个人了。但两个窗口都有人占用时同样也必须排队等待,这种多个服务窗口的同步器就是共享模式。我们先定义共享模式的同步器类,与独占模式不同的是它的状态的初始值可以自由定义,有多少个窗口就设为多少,获取与释放就是对状态递减和累加操作。需要重写AQS类的tryAcquireShared和tryReleaseShared方法,
  • 12dda835c51f4960b4a67591b7cece8c
  • 接着定义一个测试类,tom、jim和jay再次来到银行,现在因为有两个窗口所以他们可以两个人同时办理,时间缩减了不少。现在我们使用BankServiceWindowShared同步器就可以同时给两个人办理。
  • a54c94b2f0be4c6fb3abb55af23af5ec
  • 可能的输出结果如下。tom和jay几乎同时开始办理业务,而当jay结束后一有空闲的服务窗口jim就马上过去办理业务。
posted @ 2020-12-08 16:49  技术-刘腾飞  阅读(244)  评论(0编辑  收藏  举报