Davids原理探究:Java并发包中锁的原理

Java并发包中锁的原理

// 独占锁(可重入)
ReentrantLock fairLock = new ReentrantLock();
// 独占公平锁
ReentrantLock fairLock = new ReentrantLock(true);
// 独占非公平锁
ReentrantLock nonFairLock = new ReentrantLock(false);

// 读写锁(可重入)
ReentrantReadWriteLock fairReentrantReadWriteLock = new ReentrantReadWriteLock();
// 公平读写锁
ReentrantReadWriteLock fairReentrantReadWriteLock = new ReentrantReadWriteLock(true);
// 共享读
ReentrantReadWriteLock.ReadLock readLock = fairReentrantReadWriteLock.readLock();
// 独占写
ReentrantReadWriteLock.WriteLock writeLock = fairReentrantReadWriteLock.writeLock();
// 非公平读写锁
ReentrantReadWriteLock nonFairReentrantReadWriteLock = new ReentrantReadWriteLock(false);
// 共享读
ReentrantReadWriteLock.ReadLock readLock = nonFairReentrantReadWriteLock.readLock();
// 独占写
ReentrantReadWriteLock.WriteLock writeLock = nonFairReentrantReadWriteLock.writeLock();

// JDK8新增锁(不可重入)
StampedLock stampedLock = new StampedLock();
// 独占写类似于ReentrantReadWriteLock
long writeStamp = stampedLock.writeLock();
// 悲观读,CAS获取锁
long readStamp = stampedLock.readLock();
// 乐观读,不加锁(读时检查当前是否有写锁,没有则返回非0的stamp,然后读取所需的值入栈,使用前校验stampedLock.validate(stamp),期间是否有线程获取过写锁,此过程不加锁适合读多写少的场景,效率高,存在一致性问题,如果校验过后在操作的时候有线程获取写锁,并修改数据,则当前线程所获取的副本,会存在不一致,若无法接受,则需使用悲观锁。)
long stamp = stampedLock.tryOptimisticRead();

ReentrantLock公平锁

static final class FairSync extends Sync {
    private static final long serialVersionUID = -3000897897090466540L;

    final void lock() {
        acquire(1);
    }

    protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
			// !hasQueuedPredecessors()判断队列中是否有前置节点,如果有则放弃
            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;
    }
}

ReentrantLock非公平锁

static final class NonfairSync extends Sync {
   private static final long serialVersionUID = 7316153563782823691L;

   final void lock() {
	// 不判断是否有前置节点,根据cpu自行分配时间片执行获取锁
       if (compareAndSetState(0, 1))
           setExclusiveOwnerThread(Thread.currentThread());
       else
           acquire(1);
   }

   protected final boolean tryAcquire(int acquires) {
       return nonfairTryAcquire(acquires);
   }
}

abstract class AbstractQueuedSynchronizer - hasQueuedPredecessors实现

public final boolean hasQueuedPredecessors() {
    // 正确性取决于head是否在tail之前初始化,以及head.next是否正确(如果当前线程在队列中)
    Node t = tail; // 以相反的初始化顺序读取字段
    Node h = head;
    Node s;
    return h != t &&
        ((s = h.next) == null || s.thread != Thread.currentThread());
}

ReentrantLock抽象类sync

/** 
 * 此锁的同步控制基础。在下面将细分为公平和非公平版本。使用AQS状态来表示锁的保留数。
 */
abstract static class Sync extends AbstractQueuedSynchronizer {
   private static final long serialVersionUID = -5179523762034025860L;

   /**
    * 执行{@link Lock#lock}。子类化的主要原因是为非公平版本提供了快速路径。
    */
   abstract void lock();

   /**
    * 执行不公平的tryLock。 tryAcquire是在子类中实现的,但是都需要对trylock方法进行不公平的try。
    */
   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) // overflow
               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;
   }

   protected final boolean isHeldExclusively() {
       // 虽然我们通常必须在拥有者之前先读取状态,但无需检查当前线程是否为拥有者
       return getExclusiveOwnerThread() == Thread.currentThread();
   }

   final ConditionObject newCondition() {
       return new ConditionObject();
   }

   // 从外部类继承的方法

   final Thread getOwner() {
       return getState() == 0 ? null : getExclusiveOwnerThread();
   }

   final int getHoldCount() {
       return isHeldExclusively() ? getState() : 0;
   }

   final boolean isLocked() {
       return getState() != 0;
   }

   /**
    * 从流中重构实例(即反序列化它)。
    */
   private void readObject(java.io.ObjectInputStream s)
       throws java.io.IOException, ClassNotFoundException {
       s.defaultReadObject();
       setState(0); // 重置为解锁状态
   }
}

CopyOnWriteArrayList内部由ReentrantLock加锁实现线程安全

final transient ReentrantLock lock = new ReentrantLock();

/**
 *将指定的元素追加到此列表的末尾。
 *
 * @param e 要添加到此列表的元素
 * @return {@code true} (as specified by {@link Collection#add})
 */
public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}

/**
 * 用指定的元素替换此列表中指定位置的元素。
 *
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E set(int index, E element) {
	// 获取锁
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        E oldValue = get(elements, index);

        if (oldValue != element) {
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len);
            newElements[index] = element;
            setArray(newElements);
        } else {
            // 并非完全禁止操作;确保volatile的写语义,重刷会主内存
            setArray(elements);
        }
        return oldValue;
    } finally {
		// 释放锁
        lock.unlock();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章