• 重入锁


    重入ReentrantLock

    1. 支持一个线对同一个资源进行多次加锁。
    2. 支持锁时的公平和非公平性选择

    锁获取的公平性问题

    对锁进取的求一定先被足,那么是公平的,反之,是不公平的。ReentrantLock提供了一个构造函数(传人一个布尔值),来控制锁是否是公平的 

    1.实现

    1. 需要去识别获线程是否当前占据线程,如果是,再次成功取。 
    2. 线程重复n取了,随后在第n该锁后,其他线程才能够获取到该锁取时,数自增,锁被数自减,当数等于0表示成功放。
    //非公平获取锁
    final
    boolean nonfairTryAcquire(int acquires) {   final Thread current = Thread.currentThread();   int c = getState();   if (c == 0) {     if (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; }
    //释放锁
    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; }

    2.公平与非公平

      公平与非公平锁的别 :序是否符合FIFO 

    //公平获取锁
    protected final boolean tryAcquire(int acquires) {
      final Thread current = Thread.currentThread();
      int c = getState();
      if (c == 0) {
        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; }

    方法与nonfairTryAcquire(int acquires),唯一不同的位置判断条件多了hasQueuedPredecessors()方法,即加入了同步列中当前点是否有前驱节点的判断,如果该方法返回true表示有线程比当前线程更早地,因此需要等待前驱线取并释放之后才能继续获锁 

    测试公平和非公平锁时的区

    public class FairAndUnfairTest {
      private static Lock fairLock = new ReentrantLock2(true);
      private static Lock unfairLock = new ReentrantLock2(false);
      @Test
      public void fair() {
        testLock(fairLock);
      } 
      @Test   
    public void unfair() {     testLock(unfairLock);   }
      private
    void testLock(Lock lock) {     // 启动5个Job(略)   }
      private
    static class Job extends Thread {     private Lock lock;     public Job(Lock lock) {       this.lock = lock;     }
        public
    void run() {// 连续2次打印当前的Thread和等待队列中的Thread(略)     }   }
      private
    static class ReentrantLock2 extends ReentrantLock {     public ReentrantLock2(boolean fair) {       super(fair);     }
        public Collection
    <Thread> getQueuedThreads() {       List<Thread> arrayList = new ArrayList<Thread>(super.getQueuedThreads());       Collections.reverse(arrayList);       return arrayList;     }   } }

     察表5-6所示的果(其中每个数字代表一个线程),公平性每次都是从同步列中的第一个取到,而非公平性了一个线连续获的情况。 由于刚释线程再次获取同步状的几率会非常大 ,这样就减少了因锁切换而导致的线程上下文切换的开销



  • 相关阅读:
    chapter02“良/恶性乳腺癌肿瘤预测”的问题
    ASCII编码和Unicode编码的区别
    Spring AOP概述
    Spring 基于注解的配置
    Spring Bean作用域&FactoryBean
    Spring <bean> 之间的关系&整合多个配置文件
    Spring 方法注入
    Spring 简化装配Bean的配置方式
    Spring 注入参数详解
    vue-router 导航守卫
  • 原文地址:https://www.cnblogs.com/jimboi/p/6412603.html
Copyright © 2020-2023  润新知