
1.可重入锁
实现机制
final void lock() { //CAS的方式获取锁,设置status = 1if (compareAndSetState(0, 1)) //设置为当前线程占有setExclusiveOwnerThread(Thread.currentThread());else //判断是否需要阻塞acquire(1); //如果当前线程占有status + 1, 否则尝试占有锁}
2.多condition锁
condition队列,转移到线程阻塞队列
构建多个等待队列
3.可以设置是否为公/非公平锁
非公平锁,无需判断自己是否进入队列
公平锁会判断自己是否是头节点来保证fifo,也就是必须入队列且自己为头节点
/**在所有线程被LockSupport挂起之后,那么不论是公平锁,还是非公平锁,都是默认唤醒队列中当前线程的下一个线程然而,非公平锁的非公平体现在,tryAcquire()方法上!!!我们再回头看一下fairSync和unfairSync的tryAcquire方法核心点来了:·······························································公平锁,若队列不为空,没入队的线程不得抢锁,非公平锁,若队列不为空,没入队的线程却可以抢锁,这时后到的线程可能先抢到锁,即不公平。·······························································读者可能还会有点迷惑,那是没入队的不可以抢锁,没入队的可以抢锁我们再仔细体会这两个方法。·················如果是非公平锁,记还没进aqs队列的线程为A,在运行的线程为B,队列中B的next记为B.next。那么这个时候A和B.next是可以同时竞争这个锁的。如果是非公平锁,记还没进aqs队列的线程为A,在运行的线程为B,队列中的next记为B.next。那么这个时候tryAcquire的时候,因为有队列中还有节点,那么这个tryAcquire方法一定是false。因此这个A线程一定会进入aqs队列然后不断的for循环tryAcquire,如果队列中就剩它这个A节点了,那么在tryAcuqire中才会激活。或者在几次for循环后被LockSupport给挂起,等待他的前驱线程来唤醒它。·················*///这是公平锁protected final boolean tryAcquire(int acquires) {if (getState() == 0 && !hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {setExclusiveOwnerThread(Thread.currentThread());return true;}return false;}//这是非公平锁protected final boolean tryAcquire(int acquires) {if (getState() == 0 && compareAndSetState(0, acquires)) {setExclusiveOwnerThread(Thread.currentThread());return true;}return false;}
因此ReentrantLock 只有头节点线程A和新加入的线程B会产生竞争,也就是非公平。
4.lock的等待机制使用
加锁时循环四次尝试拿取锁,否则直接
LockSupport.park(); 精准到指定线程等待。
