zoukankan      html  css  js  c++  java
  • Java高并发26-释放锁以及ReentrantLock实例演示

    一、释放锁

    1.void unlock()方法

    • 尝试释放锁,如果当前线程持有锁,则调用该方法会让该线程对该线程持有的AQS状态值减1,如果减去1后当前状态值为0,则当前线程会释放该锁,否则仅仅减去1而已,如果当前线程没有持有该锁而调用了该方法就会抛出IllegalMonitorStateException异常,代码如下
     public void unlock() {
      sync.release();
     }
     
     public final boolean tryReleaseint releases) {
      // 如果不是锁持有者,则调用 unlock则抛出异常
      int c = getState() - releases;
      if(Thread.currentThread() != getExclusiveOwnerThread()) {
       throw new IllegalMonitorStateException();
      }
      boolean free = false;
      // 如果当前可重入的次数为0,则清空锁持有线程
      if(c == 0) {
       free = true;
       setExclusiveOwnerThread(null);
      }
      // 设置可重入次数为原始值-1
      setState(c);
      return free;
     }
    • 如上述代码,如果当前线程不是该锁的持有者则直接抛出异常,否则查看状态值是否为0,为0则说明当前线程要放弃对该锁的持有权,则执行代码把当前锁的持有者设置为null,如果状态值不为0,则仅仅让当前线程对该锁的可重入次数减1.

    2.下面以一个案例作为讲解

    package com.ruigege.LockSourceAnalysis6;

    import java.util.ArrayList;

    public static class ReentrantLockList {

     //线程不安全的List
     private ArrayList<String> array = new ArrayList<String>();
     //独占锁
     private volatile ReentrantLock lock = new ReentrantLock();
     
     //添加元素
     public void add(String e) {
      lock.lock();
      try {
       array.add(e);
      }finally {
       lcok.unlock();
      }
     }
     //删除元素
     public void remove(String e) {
      lock.lock();
      try {
       array.remove(e);
      }finally {
       lock.unlock();
      }
     }
     
     //获取数据
     public String get(int index) {
      lock.lock();
      try {
       return array.get(index);
      }finally {
       lock.unlock();
      }
     }
    }
    • 上述代码实现了一个线程不安全的array,当一个线程获取到锁的时候,进行一系列的增删改查,如果有其他线程想要获取到该锁,那么就会被放到AQS的队列中,等待第一个线程释放锁,来供它们获取。

    二、读写锁ReentrantReadWriteLock的原理

    • 解决线程安全问题只需要ReentrantLock即可,但是大多数情况下,该锁是独占锁,某时只有一个线程可以获取到该锁,那么实际上大多情况是写少读多,显然这个场景是无法满足的。所以ReentrantReadWriteLock就应运而生了,ReentrantReadWriteLock采用的时读写分离的策略,可以允许多个线程同时获取锁。
    • 我们下次再来解析这个类

    三、源码:

  • 相关阅读:
    Uniapp实现微信小程序云开发
    laravel 打印日志
    windbg 学习笔记
    Spring事务,非事务方法调用事务方法,事务不生效
    MyBatis 流式查询
    写代码有这16个好习惯,可以减少80%非业务的bug
    IDEA 神级插件推荐
    OUTLOOK添加企业邮箱
    Win10环境中MATLAB R2020b安装及破解全过程讲解
    scala function vs method
  • 原文地址:https://www.cnblogs.com/ruigege0000/p/14665173.html
Copyright © 2011-2022 走看看