zoukankan      html  css  js  c++  java
  • Java并发:重入锁 ReentrantLock

    ReentrantLock 是一种可重入的互斥锁,它不像 synchronized关键字一样支持隐式的重进入,但能够使一个线程(不同的方法)重复对资源的重复加锁而不受阻塞。

    ReentrantLock 的 Java类图:

    其中抽象静态内部类 Sync 继承了 AQS,可见 ReentrantLock 是通过组合自定义同步器来实现锁的获取与释放。

    ReentrantLock 的构造函数能控制锁的公平性表现:

    1     public ReentrantLock(boolean fair) {
    2         sync = fair ? new FairSync() : new NonfairSync();
    3     }

    公平锁的够减少“饥饿”发生概率,等待越久的请求越能够优先的到满足。

    公平性与否是针对获取锁而言的,一个锁若是公平的,那么锁的获取顺序就应该符合请求的绝对时间顺序,先到先得。

    公平性锁每次都是从同步队列中的第一个节点获取到锁,而非公平性锁会出现一个线程连续获取锁的情况,特别是刚释放锁的线程在次获取同步状态的几率会更大,使得其他线程在同步队列中等待。

    在系统线程上下文切换方面上,非公平性锁的切换次数会明显少于公平性锁,因为公平性锁的切换开销相对更大,但是极少的线程切换能保证更大吞吐量。

    ReentrantLock 类代码的基本结构:

     1 public class ReentrantLock implements Lock, java.io.Serializable {
     2     private final Sync sync;
     3 
     4     //默认无参构造函数,默认为非公平锁
     5     public ReentrantLock() {
     6         sync = new NonfairSync();
     7     }
     8 
     9     //带参数的构造函数,决定是公平锁还是非公平锁
    10     public ReentrantLock(boolean fair) {
    11         sync = fair ? new FairSync() : new NonfairSync();
    12     }
    13 
    14     //抽象基类继承AQS,公平锁与非公平锁继承该类,并分别实现其lock()方法
    15     abstract static class Sync extends AbstractQueuedSynchronizer {
    16         abstract void lock();
    17         //省略..
    18     }
    19     
    20     //非公平锁实现
    21     static final class NonfairSync extends Sync {...}
    22     
    23     //公平锁实现
    24     static final class FairSync extends Sync {....}
    25    
    26     //锁实现,根据具体子类实现调用
    27     public void lock() {
    28         sync.lock();
    29     }
    30 
    31     //响应中断的获取锁
    32     public void lockInterruptibly() throws InterruptedException {
    33         sync.acquireInterruptibly(1);
    34     }
    35 
    36     //尝试获取锁,默认采用非公平锁方法实现
    37     public boolean tryLock() {
    38         return sync.nonfairTryAcquire(1);
    39     }
    40 
    41     //超时获取锁
    42     public boolean tryLock(long timeout, TimeUnit unit)
    43             throws InterruptedException {
    44         return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    45     }
    46 
    47     //释放锁
    48     public void unlock() {
    49         sync.release(1);
    50     }
    51 
    52     //创建锁条件(从Condetion来理解,就是创建等待队列)
    53     public Condition newCondition() {
    54         return sync.newCondition();
    55     }
    56 
    57     //省略....
    58 }

    ReentrantLock 释放锁的方法,在抽象静态内部类 Sync 中,它会检查当前线程同步状态值(重复获取一次锁,状态值会增加),在释放同步状态时减少同步状态值,若该锁获取了 n 次,那么前(n-1)次返回的都是 false,只有同步状态完全释放了(c为0),才会把占有该资源的线程设置为空,并返回 true。

     1     protected final boolean tryRelease(int releases) {
     2             int c = getState() - releases;
     3             if (Thread.currentThread() != getExclusiveOwnerThread())
     4                 throw new IllegalMonitorStateException();
     5             boolean free = false;
     6             if (c == 0) {
     7                 free = true;
     8                 setExclusiveOwnerThread(null);
     9             }
    10             setState(c);
    11             return free;
    12         }
  • 相关阅读:
    [原]openstack-kilo--issue(十一)Failed connect to 169.254.169.254:80; No route to host
    [转]pycharm active code
    [原]openstack-kilo--issue(九) heat stacks topology中图形无法正常显示
    [原]CentOS 7 网卡子接口的创建
    [转]Shell中read的常用方式
    [转]输出带颜色的shell
    第十七节:从状态机的角度async和await的实现原理(新)
    第十六节:时隔两年再谈异步及深度剖析async和await(新)
    第十一节:SQLServer事务写法、各种锁、事务隔离级别
    第十七节:SQL中的一些常用SQL积累(持续更新)
  • 原文地址:https://www.cnblogs.com/magic-sea/p/11586548.html
Copyright © 2011-2022 走看看