• Java多线程中的可重入锁


    可重入锁

    • 可重入锁ReentrantLock,就是支持可重入的锁,他表示该锁能够支持一个线程对资源的重复加锁。

    分类

    1. 公平锁
      该锁满足在队列中进行自旋等待的线程等待时间最长的一定先获取锁,获取过程一定是顺序的。
    2. 非公平锁
      在一个线程在获取到了锁后,在绝对的时间内,该线程对锁的获取请求一定先被满足

    实现重进入

    1. 线程再次获取锁。锁需要去识别获取锁的线程是否为当前占据锁的线程。如果是则获取成功。
    2. 所得最终释放。线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够获取到该锁。锁的最终释放要求对获取进行计数自增,获取是增加,释放时减少,当计数为0时表示已经成功释放。

    可重入锁的实现

    非公平锁

    //锁的获取
    final boolean nonfairTryAcquire(int acquires) {
      			//获取到当前线程
                final Thread current = Thread.currentThread();
      			//获取同步器的状态记录
                int c = getState();
                if (c == 0) {
                    //通过CAS安全的进行状态数的更新
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
      		  //判断当前获取锁的线程是否为申请线程
                else if (current == getExclusiveOwnerThread()) {
                  	//记录数增加
                    int nextc = c + acquires;
                    if (nextc < 0) // overflow
                        throw new Error("Maximum lock count exceeded");
                  	//设置状态数
                    setState(nextc);
                    return true;
                }
                return false;
            }
    
    //锁的释放
    protected final boolean tryRelease(int releases) {
                int c = getState() - releases;
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                boolean free = false;
                if (c == 0) {
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                setState(c);
                return free;
            }
    

    公平锁

    protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                  	//与非公平锁不同点在于该判断条件增加了hasQueuedPredecessors()判断是否为等待对列的头结点
                    if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
                    if (nextc < 0)
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
        }
    
    //重入默认为非公平的,不过可以通过构造函数来确定使用哪一种锁	
    public ReentrantLock() {
            sync = new NonfairSync();
        }
        public ReentrantLock(boolean fair) {
            sync = (fair)? new FairSync() : new NonfairSync();
        }
    
  • 相关阅读:
    dynamic和匿名对象
    生成1亿个不重复的8位随机整数
    Storage,Memcache,KVDB都是存储服务,如何区分何时用何种服务
    深入理解jQuery中$.get、$.post、$.getJSON和$.ajax的用法
    常用工具
    数字格式化,保留一位小数,无小数用0补充
    学习某些API的方法
    程序员的学习方法(程序员必看)【风中叶老师讲述】
    html的dtd声明
    数据库管理工具navicat基本使用方法——以MySql为例
  • 原文地址:https://www.cnblogs.com/sev7en-/p/6770605.html
Copyright © 2020-2023  润新知