1 话题引入-lock 简单使用
ReentrantLock
/**
* j.u.c Lock 接口
*/
public class LockDemo {
// 重入锁
private Lock lock = new ReentrantLock();
private int i = 0;
public void add () {
try {
lock.lock();
i = i+1;
System.out.println(i);
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
LockDemo lockDemo = new LockDemo();
for (int i = 0; i<10 ; i++) {
new Thread(()->{
lockDemo.add();
}).start();
}
}
}
入手点 ReentrantLock
- ReentrantLock 稍微看下jdk 的实现
* @since 1.5
* @author Doug Lea
*/
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
/** Synchronizer providing all implementation mechanics */
private final Sync sync;
/** 内部类
* Base of synchronization control for this lock. Subclassed
* into fair and nonfair versions below. Uses AQS state to
* represent the number of holds on the lock.
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
abstract void lock();
.............
/**
* 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);
}
}
...............
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() { // 默认构造器
sync = new NonfairSync();
}
.......
上面是部分 代码,调用顺序
- new ReentrantLock() --> sync = new NonfairSync();
- NonfairSync extends Sync ;
- Sync extends AbstractQueuedSynchronizer ;
到这里我们就 看到了 AQS
- AbstractQueuedSynchronizer
AbstractQueuedSynchronizer 内部采用了 双向链表来存储 等待执行的线程。分析之前我们先来看一下 java 实现的双向链表:
- 双向链表
/**
* 双向链表
*/
public class Node {
/**
* 前一个结点
*/
private Node pre;
/**
* 后一个节点
*/
private Node next;
/**
* 头节点,指向第一个 节点
*/
private Node header;
/**
* 尾节点,指向最后一个节点
*/
private Node tail;
/**
* 节点数据
*/
private Object data;
public Node(Object data) {
this.data = data;
}
public Node() {
}
/**
* 向链表中添加一个节点,从尾部插入
* @param newNode
*/
public void addNode (Node newNode) {
// 当前 尾部节点
Node currentTail = this.tail;
newNode.pre = currentTail;
currentTail.next = newNode;
this.tail = newNode;
}
public void print () {
Node next = this.header.next;
while (next != null) {
System.out.println(next.data.toString());
next = next.next;
}
}
public static void main(String[] args) {
Node list = new Node();
Node header = new Node();
// 初始化 链表, header == tail
list.header = header;
list.tail = header;
list.addNode(new Node(1));
list.addNode(new Node(2));
list.addNode(new Node(4));
list.addNode(new Node(3));
//输出
list.print();
}
}
我们温习了一些 双向链表,在分析 AQS 之前,还需要分析一个基础知识 CAS,下一篇文章我们就来学习CAS
网友评论