Lock源码
public interface Lock { //获取锁 void lock(); /** *当前线程的锁没有中断才能获取锁 * if (Thread.interrupted()) * throw new InterruptedException(); */ void lockInterruptibly() throws InterruptedException; //获取锁是否成功。true表示获取到锁,false表示没有获取到锁 boolean tryLock(); // 尝试获取锁,并等待指定的时间 boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 释放锁 void unlock(); // LOCK条件 Condition newCondition();}
ReentrantLock源码
public class ReentrantLock implements Lock, java.io.Serializable { // 同步器,是整个锁机制的实现者 private final Sync sync; // 定义的抽象静态内部类。实现基本的功能 abstract static class Sync extends AbstractQueuedSynchronizer { // 抽象方法。由公平锁和非公平锁自己实现 abstract void lock(); // 释放锁 protected final boolean tryRelease(int releases) { // 锁的计数器。释放一次计数器减1,直到为0,则整个锁完全释放,才能被其他线程获取该锁。 int c = getState() - releases; // 此类型锁是可重入锁。因此是以thread为粒度的。必须判断当前线程是否与持有锁线程一致。 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; // 当锁的计数器为0时,整个锁释放。 if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } // 默认实现的一个非公平锁的获取尝试获取方法 final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); // 如果锁的计数器为0,则表示没有锁。 if (c == 0) { // compareAndSetState方法实际调用的是unsafe.compareAndSwapInt(this, stateOffset, expect, update); // 直接操作的JVM。并给当前线程持有锁。 if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // 如果计数器不为0,但当前线程就是持有锁的线程。则锁的计数器增加。 else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } // 如果计数器不为0,同时当前线程不是持有锁的线程。则加锁失败。 return false; } } // 非公平所的实现器 static final class NonfairSync extends Sync { // 加锁。 final void lock() { if (compareAndSetState(0, 1)) //非公平加锁 setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); // 如果加锁不成功,则放入队列 } // 试着加锁 protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } // 公平锁 static final class FairSync extends Sync { // 加锁,队列 final void lock() { acquire(1); } // 试着加锁 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; } }}
AbstractQueuedSynchronizer源码
// 存储队列锁的存储node.是一个双向的链表结构。 static final class Node { // 前一个node volatile Node prev; // 后一个node volatile Node next; // 该node所对应的线程 volatile Thread thread; } // 整个队列锁的第一个node. private transient volatile Node head; // 整个队列锁的第后个node. private transient volatile Node tail; // 锁的状态。计数器 private volatile int state; // 加锁的关键点。通过navtive 方法unsafe直接操作CPU。 protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); }
总结
Lock这种以类的方式来实现锁的机制。
优点:
1.加锁和释放锁独立,可以分开来控制。
2.tryLock的方法可以尝试加锁,不会像sychnorized一致阻塞。
3.实现了公平锁和非公平锁。sychnorized只能是非公平锁。
缺点:
1.增加了代码的复杂度。
2.相比sychnorized的自动加锁和释放锁,Lock需要手动,容易忘记,从而出现重大的隐患。
经过JDK的不断更新,sychnorized与lock的性能相差不大,官方建议使用sychnorized方法加锁。