Detailed Explanation of java Unfair Lock Knowledge Point Example

  • 2021-11-30 00:08:06
  • OfStack

1. Unfair locks cannot guarantee that locks are acquired in the order in which they are requested. This may cause one or more threads to never get a lock.

2. The cost of CPU waking threads can be reduced, and the overall throughput efficiency will be very high. However, the thread may not be locked for a long time or even never, resulting in starvation.

Instances


 /**
     * Sync object for non-fair locks
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
 
        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }
 
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
 
    /**
     * Sync object for fair locks
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;
 
        final void lock() {
            acquire(1);
        }
 
        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        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;
        }
    }

Extension of knowledge points:

Unfair lock, as its name implies, the order in which each thread acquires the lock does not depend on the order in which they apply. It is possible that the later thread acquires the lock first.

In implementation, the fair lock performs tryAcquire () first when performing lock. In tryAcquire, it is determined whether another thread is already waiting in the wait queue. If there are already other threads in the queue, tryAcquire fails and you join the queue yourself. If there are no other threads in the queue, the lock is acquired.


/**
     * Fair version of tryAcquire. Don't grant access unless
     * recursive call or no waiters or is first.
     **/
    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;
    }

Unfair lock, during lock, will try to lock directly. If it succeeds, it will acquire the lock. If it fails, it will perform the same action as fair lock.


Related articles: