• 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         }
  • 相关阅读:
    linq to sql 还没解决的问题
    js暂停函数,想做牛人的菜鸟遇到了问题。
    公司给我拿800/月 干不干啊?ASP.NET程序员
    android の Handler消息传递机制
    android の Activity & View | LayoutInflate
    ActionScript事件侦听addEventListener的参数详解
    java中String的intern方法和equals方法的使用
    java中short,int转换成byte数组及byte数组转换成short,int
    Flex组件中list里面的数据引用
    Flex中设置弹出窗口的弹出效果(alpha值的渐变和scale值的渐变)
  • 原文地址:https://www.cnblogs.com/magic-sea/p/11586548.html
Copyright © 2020-2023  润新知