chapter13_显式锁_1_Lock与ReentrantLock

  • (1) Lock是一个接口, 它提供了一种无条件的、可轮询的、定时的、可中断的锁获取操作m 所有加锁和解锁的方法都是__显式__的

      public interface Lock {
    
          void lock();
    
          void lockInterruptibly() throws InterruptedException;
    
          boolean tryLock();
    
          boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    
          void unlock();
    
          Condition newCondition();
    
      }
    

    (2) Lock的实现中, 和内置锁synchronized的内存可见性语义相同, 在加锁语义、调度算法、顺序保证以及性能特性等方面有所不同

  • (1) ReentrantLock是Lock接口的一种实现, 它与synchronized具有相同的互斥性和内存可见性

    (2) 使用Lock时, 必须显式unlock(), 否则永远不会被释放, 所以要在finally中释放

      Lock lock = new ReentrantLock();
    
      lock.lock();
    
      try {
          ...
      } catch () {
          ...
      } finally {
          lock.unlock();
      }
    
  • 使用Lock作为__轮询锁__

    (1) 示例

      public class DeadlockAvoidance {
    
          ...
    
          public boolean transferMoney(
              Account fromAcct, Account toAcct,
              DollarAmount amount, long timeout, TimeUnit unit)
              throws InsufficientFundsException, InterruptedException {
    
              long fixedDelay = getFixedDelayComponentNanos(timeout, unit);
              long randMod = getRandomDelayModulusNanos(timeout, unit);
      
              long stopTime = System.nanoTime() + unit.toNanos(timeout);
    
              while (true) {
    
                  if (fromAcct.lock.tryLock()) {
    
                      try {
                          if (toAcct.lock.tryLock()) {
    
                              try {
                                  if (fromAcct.getBalance().compareTo(amount) < 0) {
                                      throw new InsufficientFundsException();
                                  } else {
                                      fromAcct.debit(amount);
                                      toAcct.credit(amount);
                                      return true;
                                  }
                              } finally {
                                  toAcct.lock.unlock();
                              }
                          }
                      } finally {
                          fromAcct.lock.unlock();
                      }
                  }
    
                  if (System.nanoTime() > stopTime) {
                      return false;
                  }
    
                  NANOSECONDS.sleep(fixedDelay + rnd.nextLong() % randMod);
              }    
          }
    
          ...
      }
    

    (2) boolean tryLock();方法的含义是

      /**
       *
       * <p>Acquires the lock if it is available and returns immediately
       * with the value {@code true}.
       * 
       * If the lock is not available then this method will return
       * immediately with the value {@code false}.
       *
       * <p>A typical usage idiom for this method would be:
       * <pre> {@code
       * Lock lock = ...;
       * if (lock.tryLock()) {
       *   try {
       *     // manipulate protected state
       *   } finally {
       *     lock.unlock();
       *   }
       * } else {
       *   // perform alternative actions
       * }}</pre>
       *
       * This usage ensures that the lock is unlocked if it was acquired, and
       * doesn't try to unlock if the lock was not acquired.
    

    所以无论是否获得到了锁都会立刻返回, 因此可以用作轮询

  • 使用Lock作为__定时锁__

    (1) 示例

      public class TimedLocking {
    
          private Lock lock = new ReentrantLock();
    
          public boolean trySendOnSharedLine(String message, long timeout, TimeUnit unit) throws InterruptedException {
    
              long nanosToLock = unit.toNanos(timeout) - estimatedNanosToSend(message);
    
              if (!lock.tryLock(nanosToLock, NANOSECONDS)) {
                  return false;
              }
    
              try {
                  return sendOnSharedLine(message);
              } finally {
                  lock.unlock();
              }
          }
    
          ...
      }
    

    (2) boolean tryLock(long time, TimeUnit unit) throws InterruptedException;方法的语义是

      /**
       * Acquires the lock if it is free within the given waiting time and the
       * current thread has not been {@linkplain Thread#interrupt interrupted}.
       *
       * <p>If the lock is available this method returns immediately
       * with the value {@code true}.
       * If the lock is not available then
       * the current thread becomes disabled for thread scheduling
       * purposes and lies dormant until one of three things happens:
       * <ul>
       * <li>The lock is acquired by the current thread; or
       * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
       * current thread, and interruption of lock acquisition is supported; or
       * <li>The specified waiting time elapses
       * </ul>
       *
       * <p>If the lock is acquired then the value {@code true} is returned.
       *
       * <p>If the current thread:
       * <ul>
       * <li>has its interrupted status set on entry to this method; or
       * <li>is {@linkplain Thread#interrupt interrupted} while acquiring
       * the lock, and interruption of lock acquisition is supported,
       * </ul>
       * then {@link InterruptedException} is thrown and the current thread's
       * interrupted status is cleared.
       *
       * <p>If the specified waiting time elapses then the value {@code false}
       * is returned.
       * If the time is less than or equal to zero, the method will not wait at 
       * all.
       *
       * @param time the maximum time to wait for the lock
       * @param unit the time unit of the {@code time} argument
       * @return {@code true} if the lock was acquired and {@code false}
       *         if the waiting time elapsed before the lock was acquired
       *
       * @throws InterruptedException if the current thread is interrupted
       *         while acquiring the lock (and interruption of lock
       *         acquisition is supported)
       */
    

    (3) 所以可以用来作为定时锁, 期间发生了中断也可以抛出去或者处理之

  • 使用Lock作为__可中断的锁__

    (1) 示例

      public class InterruptibleLocking {
    
          private Lock lock = new ReentrantLock();
    
          public boolean sendOnSharedLine(String message) throws InterruptedException {
    
              lock.lockInterruptibly();
    
              try {
                  return cancellableSendOnSharedLine(message);
              } finally {
                  lock.unlock();
              }
          }
    
          private boolean cancellableSendOnSharedLine(String message) throws InterruptedException {
    
              /* send something */
              return true;
          }
      }
    

    (2) void lockInterruptibly() throws InterruptedException;语义

      /**
       * Acquires the lock unless the current thread is
       * {@linkplain Thread#interrupt interrupted}.
       *
       * <p>Acquires the lock if it is available and returns immediately.
       *
       * <p>If the lock is not available then the current thread becomes
       * disabled for thread scheduling purposes and lies dormant until
       * one of two things happens:
       *
       * <ul>
       * <li>The lock is acquired by the current thread; or
       * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
       * current thread, and interruption of lock acquisition is supported.
       * </ul>
       *
       * <p>If the current thread:
       * <ul>
       * <li>has its interrupted status set on entry to this method; or
       * <li>is {@linkplain Thread#interrupt interrupted} while acquiring the
       * lock, and interruption of lock acquisition is supported,
       * </ul>
       * then {@link InterruptedException} is thrown and the current thread's
       * interrupted status is cleared.
       * 
       * @throws InterruptedException if the current thread is
       *         interrupted while acquiring the lock (and interruption
       *         of lock acquisition is supported)
       */
    

    (3) 如果既要定时又要可中断, 使用带定时的tryLock方法

猜你喜欢

转载自blog.csdn.net/captxb/article/details/88648597