# 聊聊你知道的锁

1. 你知道哪些锁？
2. 锁解决了哪些应用场景的问题？
3. 锁的底层实现？
4. java 中的并发包了解吗？
5. CAS 会有哪些问题？如何解决？
6. AQS 是并发包的基础，实现原理是什么？
7. synchronize 是可重入锁吗？

# 锁

## 可中断锁

tryLock(long time, TimeUnit unit)是加强版的tryLock()，又具有lockInterruptibly()的可被中断特性，既可任其超时主动退出又可中断让其被动退出，很多场合可以使用，但如果想让线程只有当被动中断时才退出，那么就使用lockInterruptibly()方法。

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  /* Lock接口 */ public interface Lock { void lock(); // 拿不到锁就一直等，拿到马上返回。 void lockInterruptibly() throws InterruptedException; // 拿不到锁就一直等，如果等待时收到中断请求，则需要处理InterruptedException。 boolean tryLock(); // 无论拿不拿得到锁，都马上返回。拿到返回true，拿不到返回false。 boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 同上，可以自定义等待的时间。 void unlock(); Condition newCondition(); } 
• 内部锁(synchronized) 优先响应锁获取再响应中断
• Lock.lock() 优先响应锁获取再响应中断
• Lock.tryLock() 判断锁的状态不可用后马上返回不等待
• tryLock(long time, TimeUnit unit) 优先响应中断再响应锁获取
• Lock.lockInterruptibly() 优先响应中断再响应锁获取

## 读写锁、互斥锁、共享锁

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22   /** @see ReentrantReadWriteLock * @see Lock * @see ReentrantLock * * @since 1.5 * @author Doug Lea */ public interface ReadWriteLock { /** * Returns the lock used for reading. * * @return the lock used for reading */ Lock readLock(); /** * Returns the lock used for writing. * * @return the lock used for writing */ Lock writeLock(); } 

# Java中的悲观锁、乐观锁

  1 2 3 4 5 6 7 8 9 10 11 12  /** * Atomically sets the value to the given updated value * if the current value {@code ==} the expected value. * * @param expect the expected value * @param update the new value * @return {@code true} if successful. False return indicates that * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } 

# cas中的ABA问题及解决方案

## cas

CAS（CompareAndSet）是保证并发安全性的一条CPU底层原子指令，它的功能是判断某个值是否为预期值，如果是的话，就改为新值，在CAS过程中不会被中断。

## 危害

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41  Node head; head = B; A.next = head; head = A; Thread thread1 = new Thread( ->{ oldValue = head; sleep(3秒); compareAndSet(oldValue, B); } ); Thread thread2 = new Thread( ->{ // 弹出A newHead = head.next; head.next = null; //即A.next = null; head = newHead; // 弹出B newHead = head.next; head = newHead; // 此时head为null // 压入C head = C; // 压入D D.next = head; head = D; // 压入A A.next = D; head = A; } ); thread1.start(); thread2.start(); 

# AQS

AbstractQueuedSynchronizer （AQS ）， 抽象的队列式同步器，并发包的基础

AQS 的核心功能，就是用来将当前工作的线程设置为占有资源状态，并将资源状态设置为锁定，如果其他线程继续访问共享资源， 则需要使用队列将其他线程进行管理，这个队列并不是实例化的某种队列，只是一个 Node 节点的双向关联。

1. FIFO 先入先出队列
2. 状态控制（volatile修饰共享变量state）
3. lock获取锁的过程：本质上是通过CAS来获取状态值修改，如果当场没获取到，会将该线程放在线程等待链表中
4. lock释放锁的过程：修改状态值，调整等待链表。

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104   static final class Node { /** Marker to indicate a node is waiting in shared mode */ static final Node SHARED = new Node(); /** Marker to indicate a node is waiting in exclusive mode */ static final Node EXCLUSIVE = null; /** waitStatus value to indicate thread has cancelled */ static final int CANCELLED = 1; /** waitStatus value to indicate successor's thread needs unparking */ static final int SIGNAL = -1; /** waitStatus value to indicate thread is waiting on condition */ static final int CONDITION = -2; /** * waitStatus value to indicate the next acquireShared should * unconditionally propagate */ static final int PROPAGATE = -3; /** * Status field, taking on only the values: * SIGNAL: The successor of this node is (or will soon be) * blocked (via park), so the current node must * unpark its successor when it releases or * cancels. To avoid races, acquire methods must * first indicate they need a signal, * then retry the atomic acquire, and then, * on failure, block. * CANCELLED: This node is cancelled due to timeout or interrupt. * Nodes never leave this state. In particular, * a thread with cancelled node never again blocks. * CONDITION: This node is currently on a condition queue. * It will not be used as a sync queue node * until transferred, at which time the status * will be set to 0. (Use of this value here has * nothing to do with the other uses of the * field, but simplifies mechanics.) * PROPAGATE: A releaseShared should be propagated to other * nodes. This is set (for head node only) in * doReleaseShared to ensure propagation * continues, even if other operations have * since intervened. * 0: None of the above * * The values are arranged numerically to simplify use. * Non-negative values mean that a node doesn't need to * signal. So, most code doesn't need to check for particular * values, just for sign. * * The field is initialized to 0 for normal sync nodes, and * CONDITION for condition nodes. It is modified using CAS * (or when possible, unconditional volatile writes). */ volatile int waitStatus; volatile Node prev; volatile Node next; /** * The thread that enqueued this node. Initialized on * construction and nulled out after use. */ volatile Thread thread; Node nextWaiter; /** * Returns true if node is waiting in shared mode. */ final boolean isShared() { return nextWaiter == SHARED; } /** * Returns previous node, or throws NullPointerException if null. * Use when predecessor cannot be null. The null check could * be elided, but is present to help the VM. * * @return the predecessor of this node */ final Node predecessor() throws NullPointerException { Node p = prev; if (p == null) throw new NullPointerException(); else return p; } Node() { // Used to establish initial head or SHARED marker } Node(Thread thread, Node mode) { // Used by addWaiter this.nextWaiter = mode; this.thread = thread; } Node(Thread thread, int waitStatus) { // Used by Condition this.waitStatus = waitStatus; this.thread = thread; } } 

# synchronized是不是可重入锁

synchronized 是一个可重入锁