zoukankan      html  css  js  c++  java
  • 重入锁

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



  • 相关阅读:
    uva 10369 Arctic Network
    uvalive 5834 Genghis Khan The Conqueror
    uvalive 4848 Tour Belt
    uvalive 4960 Sensor Network
    codeforces 798c Mike And Gcd Problem
    codeforces 796c Bank Hacking
    codeforces 768c Jon Snow And His Favourite Number
    hdu 1114 Piggy-Bank
    poj 1276 Cash Machine
    bzoj 2423 最长公共子序列
  • 原文地址:https://www.cnblogs.com/jimboi/p/6412603.html
Copyright © 2011-2022 走看看